<!DOCTYPE html><html lang="zh-CN" data-theme="light"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"><title>JVM系列-第6章-方法区 | 石银的小酒屋</title><meta name="keywords" content="JVM，虚拟机。"><meta name="author" content="Alix"><meta name="copyright" content="Alix"><meta name="format-detection" content="telephone=no"><meta name="theme-color" content="#ffffff"><meta name="description" content="JVM系列-第6章-方法区。">
<meta property="og:type" content="article">
<meta property="og:title" content="JVM系列-第6章-方法区">
<meta property="og:url" content="http://example.com/2021/11/13/JVM/JVM%E7%B3%BB%E5%88%97-%E7%AC%AC6%E7%AB%A0-%E6%96%B9%E6%B3%95%E5%8C%BA/index.html">
<meta property="og:site_name" content="石银的小酒屋">
<meta property="og:description" content="JVM系列-第6章-方法区。">
<meta property="og:locale" content="zh_CN">
<meta property="og:image" content="https://npm.elemecdn.com/lql_static@latest/logo/jvm.png">
<meta property="article:published_time" content="2021-11-13T11:38:42.000Z">
<meta property="article:modified_time" content="2023-04-20T10:48:54.133Z">
<meta property="article:author" content="Alix">
<meta property="article:tag" content="JVM">
<meta property="article:tag" content="虚拟机">
<meta name="twitter:card" content="summary">
<meta name="twitter:image" content="https://npm.elemecdn.com/lql_static@latest/logo/jvm.png"><link rel="shortcut icon" href="/assetse/%E5%A4%B4%E5%83%8F.jpg"><link rel="canonical" href="http://example.com/2021/11/13/JVM/JVM%E7%B3%BB%E5%88%97-%E7%AC%AC6%E7%AB%A0-%E6%96%B9%E6%B3%95%E5%8C%BA/"><link rel="preconnect" href="//cdn.jsdelivr.net"/><link rel="preconnect" href="//busuanzi.ibruce.info"/><link rel="stylesheet" href="/css/index.css"><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free/css/all.min.css" media="print" onload="this.media='all'"><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fancyapps/ui/dist/fancybox.min.css" media="print" onload="this.media='all'"><script>const GLOBAL_CONFIG = { 
  root: '/',
  algolia: undefined,
  localSearch: undefined,
  translate: undefined,
  noticeOutdate: undefined,
  highlight: {"plugin":"highlighjs","highlightCopy":true,"highlightLang":true,"highlightHeightLimit":false},
  copy: {
    success: '复制成功',
    error: '复制错误',
    noSupport: '浏览器不支持'
  },
  relativeDate: {
    homepage: false,
    post: false
  },
  runtime: '',
  date_suffix: {
    just: '刚刚',
    min: '分钟前',
    hour: '小时前',
    day: '天前',
    month: '个月前'
  },
  copyright: undefined,
  lightbox: 'fancybox',
  Snackbar: undefined,
  source: {
    justifiedGallery: {
      js: 'https://cdn.jsdelivr.net/npm/flickr-justified-gallery/dist/fjGallery.min.js',
      css: 'https://cdn.jsdelivr.net/npm/flickr-justified-gallery/dist/fjGallery.min.css'
    }
  },
  isPhotoFigcaption: false,
  islazyload: false,
  isAnchor: false
}</script><script id="config-diff">var GLOBAL_CONFIG_SITE = {
  title: 'JVM系列-第6章-方法区',
  isPost: true,
  isHome: false,
  isHighlightShrink: false,
  isToc: true,
  postUpdate: '2023-04-20 18:48:54'
}</script><noscript><style type="text/css">
  #nav {
    opacity: 1
  }
  .justified-gallery img {
    opacity: 1
  }

  #recent-posts time,
  #post-meta time {
    display: inline !important
  }
</style></noscript><script>(win=>{
    win.saveToLocal = {
      set: function setWithExpiry(key, value, ttl) {
        if (ttl === 0) return
        const now = new Date()
        const expiryDay = ttl * 86400000
        const item = {
          value: value,
          expiry: now.getTime() + expiryDay,
        }
        localStorage.setItem(key, JSON.stringify(item))
      },

      get: function getWithExpiry(key) {
        const itemStr = localStorage.getItem(key)

        if (!itemStr) {
          return undefined
        }
        const item = JSON.parse(itemStr)
        const now = new Date()

        if (now.getTime() > item.expiry) {
          localStorage.removeItem(key)
          return undefined
        }
        return item.value
      }
    }
  
    win.getScript = url => new Promise((resolve, reject) => {
      const script = document.createElement('script')
      script.src = url
      script.async = true
      script.onerror = reject
      script.onload = script.onreadystatechange = function() {
        const loadState = this.readyState
        if (loadState && loadState !== 'loaded' && loadState !== 'complete') return
        script.onload = script.onreadystatechange = null
        resolve()
      }
      document.head.appendChild(script)
    })
  
      win.activateDarkMode = function () {
        document.documentElement.setAttribute('data-theme', 'dark')
        if (document.querySelector('meta[name="theme-color"]') !== null) {
          document.querySelector('meta[name="theme-color"]').setAttribute('content', '#0d0d0d')
        }
      }
      win.activateLightMode = function () {
        document.documentElement.setAttribute('data-theme', 'light')
        if (document.querySelector('meta[name="theme-color"]') !== null) {
          document.querySelector('meta[name="theme-color"]').setAttribute('content', '#ffffff')
        }
      }
      const t = saveToLocal.get('theme')
    
          if (t === 'dark') activateDarkMode()
          else if (t === 'light') activateLightMode()
        
      const asideStatus = saveToLocal.get('aside-status')
      if (asideStatus !== undefined) {
        if (asideStatus === 'hide') {
          document.documentElement.classList.add('hide-aside')
        } else {
          document.documentElement.classList.remove('hide-aside')
        }
      }
    
    const detectApple = () => {
      if(/iPad|iPhone|iPod|Macintosh/.test(navigator.userAgent)){
        document.documentElement.classList.add('apple')
      }
    }
    detectApple()
    })(window)</script><link rel="stylesheet" href="/self/Kimbiedark.css"><meta name="generator" content="Hexo 6.2.0"><link rel="alternate" href="/atom.xml" title="石银的小酒屋" type="application/atom+xml">
</head><body><div id="loading-box"><div class="loading-left-bg"></div><div class="loading-right-bg"></div><div class="spinner-box"><div class="configure-border-1"><div class="configure-core"></div></div><div class="configure-border-2"><div class="configure-core"></div></div><div class="loading-word">加载中...</div></div></div><div id="web_bg"></div><div id="sidebar"><div id="menu-mask"></div><div id="sidebar-menus"><div class="avatar-img is-center"><img src="/assetse/%E5%A4%B4%E5%83%8F.jpg" onerror="onerror=null;src='/img/friend_404.gif'" alt="avatar"/></div><div class="sidebar-site-data site-data is-center"><a href="/archives/"><div class="headline">文章</div><div class="length-num">23</div></a><a href="/tags/"><div class="headline">标签</div><div class="length-num">9</div></a><a href="/categories/"><div class="headline">分类</div><div class="length-num">7</div></a></div><hr/><div class="menus_items"><div class="menus_item"><a class="site-page" href="/"><i class="fa-fw fas fa-home"></i><span> 主页</span></a></div><div class="menus_item"><a class="site-page group" href="javascript:void(0);"><i class="fa-fw fa fa-graduation-cap"></i><span> 博文</span><i class="fas fa-chevron-down"></i></a><ul class="menus_item_child"><li><a class="site-page child" href="/categories/"><i class="fa-fw fa fa-archive"></i><span> 分类</span></a></li><li><a class="site-page child" href="/tags/"><i class="fa-fw fa fa-tags"></i><span> 标签</span></a></li><li><a class="site-page child" href="/archives/"><i class="fa-fw fa fa-folder-open"></i><span> 归档</span></a></li></ul></div><div class="menus_item"><a class="site-page group" href="javascript:void(0);"><i class="fa-fw fas fa-list"></i><span> 生活</span><i class="fas fa-chevron-down"></i></a><ul class="menus_item_child"><li><a class="site-page child" href="/photos/"><i class="fa-fw fa fa-camera-retro"></i><span> 相册</span></a></li><li><a class="site-page child" href="/playlist/"><i class="fa-fw fa fa-music"></i><span> 音乐</span></a></li><li><a class="site-page child" href="/bangumis/"><i class="fa-fw fas fa-video"></i><span> 番剧</span></a></li></ul></div><div class="menus_item"><a class="site-page" href="/link/"><i class="fa-fw fa fa-link"></i><span> 友链</span></a></div><div class="menus_item"><a class="site-page" href="/about/"><i class="fa-fw fas fa-heart"></i><span> 关于笔者</span></a></div></div></div></div><div class="post" id="body-wrap"><header class="post-bg" id="page-header" style="background-image: url('https://npm.elemecdn.com/lql_static@latest/logo/jvm.png')"><nav id="nav"><span id="blog_name"><a id="site-name" href="/">石银的小酒屋</a></span><div id="menus"><div class="menus_items"><div class="menus_item"><a class="site-page" href="/"><i class="fa-fw fas fa-home"></i><span> 主页</span></a></div><div class="menus_item"><a class="site-page group" href="javascript:void(0);"><i class="fa-fw fa fa-graduation-cap"></i><span> 博文</span><i class="fas fa-chevron-down"></i></a><ul class="menus_item_child"><li><a class="site-page child" href="/categories/"><i class="fa-fw fa fa-archive"></i><span> 分类</span></a></li><li><a class="site-page child" href="/tags/"><i class="fa-fw fa fa-tags"></i><span> 标签</span></a></li><li><a class="site-page child" href="/archives/"><i class="fa-fw fa fa-folder-open"></i><span> 归档</span></a></li></ul></div><div class="menus_item"><a class="site-page group" href="javascript:void(0);"><i class="fa-fw fas fa-list"></i><span> 生活</span><i class="fas fa-chevron-down"></i></a><ul class="menus_item_child"><li><a class="site-page child" href="/photos/"><i class="fa-fw fa fa-camera-retro"></i><span> 相册</span></a></li><li><a class="site-page child" href="/playlist/"><i class="fa-fw fa fa-music"></i><span> 音乐</span></a></li><li><a class="site-page child" href="/bangumis/"><i class="fa-fw fas fa-video"></i><span> 番剧</span></a></li></ul></div><div class="menus_item"><a class="site-page" href="/link/"><i class="fa-fw fa fa-link"></i><span> 友链</span></a></div><div class="menus_item"><a class="site-page" href="/about/"><i class="fa-fw fas fa-heart"></i><span> 关于笔者</span></a></div></div><div id="toggle-menu"><a class="site-page"><i class="fas fa-bars fa-fw"></i></a></div></div></nav><div id="post-info"><h1 class="post-title">JVM系列-第6章-方法区</h1><div id="post-meta"><div class="meta-firstline"><span class="post-meta-date"><i class="far fa-calendar-alt fa-fw post-meta-icon"></i><span class="post-meta-label">发表于</span><time class="post-meta-date-created" datetime="2021-11-13T11:38:42.000Z" title="发表于 2021-11-13 19:38:42">2021-11-13</time><span class="post-meta-separator">|</span><i class="fas fa-history fa-fw post-meta-icon"></i><span class="post-meta-label">更新于</span><time class="post-meta-date-updated" datetime="2023-04-20T10:48:54.133Z" title="更新于 2023-04-20 18:48:54">2023-04-20</time></span><span class="post-meta-categories"><span class="post-meta-separator">|</span><i class="fas fa-inbox fa-fw post-meta-icon"></i><a class="post-meta-categories" href="/categories/JVM/">JVM</a><i class="fas fa-angle-right post-meta-separator"></i><i class="fas fa-inbox fa-fw post-meta-icon"></i><a class="post-meta-categories" href="/categories/JVM/1-%E5%86%85%E5%AD%98%E4%B8%8E%E5%9E%83%E5%9C%BE%E5%9B%9E%E6%94%B6%E7%AF%87/">1.内存与垃圾回收篇</a></span></div><div class="meta-secondline"><span class="post-meta-separator">|</span><span class="post-meta-wordcount"><i class="far fa-file-word fa-fw post-meta-icon"></i><span class="post-meta-label">字数总计:</span><span class="word-count">9.6k</span><span class="post-meta-separator">|</span><i class="far fa-clock fa-fw post-meta-icon"></i><span class="post-meta-label">阅读时长:</span><span>37分钟</span></span><span class="post-meta-separator">|</span><span class="post-meta-pv-cv" id="" data-flag-title="JVM系列-第6章-方法区"><i class="far fa-eye fa-fw post-meta-icon"></i><span class="post-meta-label">阅读量:</span><span id="busuanzi_value_page_pv"><i class="fa-solid fa-spinner fa-spin"></i></span></span></div></div></div></header><main class="layout" id="content-inner"><div id="post"><article class="post-content" id="article-container"><h1 id="方法区"><a href="#方法区" class="headerlink" title="方法区"></a>方法区</h1><h2 id="栈、堆、方法区的交互关系"><a href="#栈、堆、方法区的交互关系" class="headerlink" title="栈、堆、方法区的交互关系"></a>栈、堆、方法区的交互关系</h2><p><strong>从线程共享与否的角度来看</strong></p>
<p>ThreadLocal：如何保证多个线程在并发环境下的安全性？典型场景就是数据库连接管理，以及会话管理。</p>
<img src="https://npm.elemecdn.com/youthlql@1.0.8/JVM/chapter_006/0001.png">

<p><strong>栈、堆、方法区的交互关系</strong></p>
<p><strong>下面涉及了对象的访问定位</strong></p>
<ol>
<li>Person 类的 .class 信息存放在方法区中</li>
<li>person 变量存放在 Java 栈的局部变量表中</li>
<li>真正的 person 对象存放在 Java 堆中</li>
<li>在 person 对象中，有个指针指向方法区中的 person 类型数据，表明这个 person 对象是用方法区中的 Person 类 new 出来的</li>
</ol>
<img src="https://npm.elemecdn.com/youthlql@1.0.8/JVM/chapter_006/0002.png">

<h2 id="方法区的理解"><a href="#方法区的理解" class="headerlink" title="方法区的理解"></a>方法区的理解</h2><blockquote>
<p><strong>官方文档</strong>：<a target="_blank" rel="noopener" href="https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-2.html#jvms-2.5.4">https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-2.html#jvms-2.5.4</a></p>
</blockquote>
<h3 id="方法区在哪里？"><a href="#方法区在哪里？" class="headerlink" title="方法区在哪里？"></a>方法区在哪里？</h3><ol>
<li>《Java虚拟机规范》中明确说明：尽管所有的方法区在逻辑上是属于堆的一部分，但一些简单的实现可能不会选择去进行垃圾收集或者进行压缩。但对于HotSpotJVM而言，方法区还有一个别名叫做Non-Heap（非堆），目的就是要和堆分开。</li>
<li>所以，<strong>方法区可以看作是一块独立于Java堆的内存空间</strong>。</li>
</ol>
<img src="https://npm.elemecdn.com/youthlql@1.0.8/JVM/chapter_006/0003.png">



<h3 id="方法区的基本理解"><a href="#方法区的基本理解" class="headerlink" title="方法区的基本理解"></a>方法区的基本理解</h3><p><strong>方法区主要存放的是 Class，而堆中主要存放的是实例化的对象</strong></p>
<ol>
<li>方法区（Method Area）与Java堆一样，是各个线程共享的内存区域。多个线程同时加载统一个类时，只能有一个线程能加载该类，其他线程只能等等待该线程加载完毕，然后直接使用该类，即类只能加载一次。</li>
<li>方法区在JVM启动的时候被创建，并且它的实际的物理内存空间中和Java堆区一样都可以是不连续的。</li>
<li>方法区的大小，跟堆空间一样，可以选择固定大小或者可扩展。</li>
<li>方法区的大小决定了系统可以保存多少个类，如果系统定义了太多的类，导致方法区溢出，虚拟机同样会抛出内存溢出错误：<code>java.lang.OutofMemoryError:PermGen space</code>或者<code>java.lang.OutOfMemoryError:Metaspace</code><ul>
<li>加载大量的第三方的jar包</li>
<li>Tomcat部署的工程过多（30~50个）</li>
<li>大量动态的生成反射类</li>
</ul>
</li>
<li>关闭JVM就会释放这个区域的内存。</li>
</ol>
<p><strong>代码举例</strong></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">MethodAreaDemo</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;start...&quot;</span>);</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            Thread.sleep(<span class="number">1000000</span>);</span><br><span class="line">        &#125; <span class="keyword">catch</span> (InterruptedException e) &#123;</span><br><span class="line">            e.printStackTrace();</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        System.out.println(<span class="string">&quot;end...&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<p>简单的程序，加载了1600多个类</p>
<img src="https://npm.elemecdn.com/youthlql@1.0.8/JVM/chapter_006/0004.png">



<h3 id="HotSpot方法区演进"><a href="#HotSpot方法区演进" class="headerlink" title="HotSpot方法区演进"></a>HotSpot方法区演进</h3><ol>
<li>在 JDK7 及以前，习惯上把方法区，称为永久代。JDK8开始，使用元空间取代了永久代。我们可以将方法区类比为Java中的接口，将永久代或元空间类比为Java中具体的实现类</li>
<li>本质上，方法区和永久代并不等价。仅是对Hotspot而言的可以看作等价。《Java虚拟机规范》对如何实现方法区，不做统一要求。例如：BEAJRockit &#x2F; IBM J9 中不存在永久代的概念。<ul>
<li>现在来看，当年使用永久代，不是好的idea。导致Java程序更容易OOm（超过-XX:MaxPermsize上限）</li>
</ul>
</li>
<li>而到了JDK8，终于完全废弃了永久代的概念，改用与JRockit、J9一样在本地内存中实现的元空间（Metaspace）来代替</li>
<li>元空间的本质和永久代类似，都是对JVM规范中方法区的实现。不过元空间与永久代最大的区别在于：<strong>元空间不在虚拟机设置的内存中，而是使用本地内存</strong>。</li>
<li>永久代、元空间二者并不只是名字变了，内部结构也调整了</li>
<li>根据《Java虚拟机规范》的规定，如果方法区无法满足新的内存分配需求时，将抛出OOM异常</li>
</ol>
<img src="https://npm.elemecdn.com/youthlql@1.0.8/JVM/chapter_006/0005.png">



<h2 id="设置方法区大小与-OOM"><a href="#设置方法区大小与-OOM" class="headerlink" title="设置方法区大小与 OOM"></a>设置方法区大小与 OOM</h2><p>方法区的大小不必是固定的，JVM可以根据应用的需要动态调整。</p>
<h3 id="JDK7及以前-永久代"><a href="#JDK7及以前-永久代" class="headerlink" title="JDK7及以前(永久代)"></a>JDK7及以前(永久代)</h3><ol>
<li>通过-XX:Permsize来设置永久代初始分配空间。默认值是20.75M</li>
<li>-XX:MaxPermsize来设定永久代最大可分配空间。32位机器默认是64M，64位机器模式是82M</li>
<li>当JVM加载的类信息容量超过了这个值，会报异常OutofMemoryError:PermGen space。</li>
</ol>
<img src="https://npm.elemecdn.com/youthlql@1.0.8/JVM/chapter_006/0006.png">

<h3 id="JDK8及以后-元空间"><a href="#JDK8及以后-元空间" class="headerlink" title="JDK8及以后(元空间)"></a>JDK8及以后(元空间)</h3><blockquote>
<p><strong>JDK8 版本设置元空间大小</strong></p>
</blockquote>
<ol>
<li><p>元数据区大小可以使用参数 <strong>-XX:MetaspaceSize</strong> 和 <strong>-XX:MaxMetaspaceSize</strong> 指定</p>
</li>
<li><p>默认值依赖于平台，Windows下，-XX:MetaspaceSize 约为21M，-XX:MaxMetaspaceSize的值是-1，即没有限制。</p>
</li>
<li><p>与永久代不同，如果不指定大小，默认情况下，虚拟机会耗尽所有的可用系统内存。如果元数据区发生溢出，虚拟机一样会抛出异常OutOfMemoryError:Metaspace</p>
</li>
<li><p>-XX:MetaspaceSize：设置初始的元空间大小。对于一个 64位 的服务器端 JVM 来说，其默认的 -XX:MetaspaceSize值为21MB。这就是初始的高水位线，一旦触及这个水位线，Full GC将会被触发并卸载没用的类（即这些类对应的类加载器不再存活），然后这个高水位线将会重置。新的高水位线的值取决于GC后释放了多少元空间。如果释放的空间不足，那么在不超过MaxMetaspaceSize时，适当提高该值。如果释放空间过多，则适当降低该值。</p>
</li>
<li><p>如果初始化的高水位线设置过低，上述高水位线调整情况会发生很多次。通过垃圾回收器的日志可以观察到Full GC多次调用。为了避免频繁地GC，建议将-XX:MetaspaceSize设置为一个相对较高的值。</p>
</li>
</ol>
<h3 id="方法区OOM"><a href="#方法区OOM" class="headerlink" title="方法区OOM"></a>方法区OOM</h3><p>举例：</p>
<p>代码：OOMTest 类继承 ClassLoader 类，获得 defineClass() 方法，可自己进行类的加载</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * jdk6/7中：</span></span><br><span class="line"><span class="comment"> * -XX:PermSize=10m -XX:MaxPermSize=10m</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * jdk8中：</span></span><br><span class="line"><span class="comment"> * -XX:MetaspaceSize=10m -XX:MaxMetaspaceSize=10m</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">OOMTest</span> <span class="keyword">extends</span> <span class="title class_">ClassLoader</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">        <span class="type">int</span> <span class="variable">j</span> <span class="operator">=</span> <span class="number">0</span>;</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            <span class="type">OOMTest</span> <span class="variable">test</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">OOMTest</span>();</span><br><span class="line">            <span class="keyword">for</span> (<span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">0</span>; i &lt; <span class="number">10000</span>; i++) &#123;</span><br><span class="line">                <span class="comment">//创建ClassWriter对象，用于生成类的二进制字节码</span></span><br><span class="line">                <span class="type">ClassWriter</span> <span class="variable">classWriter</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">ClassWriter</span>(<span class="number">0</span>);</span><br><span class="line">                <span class="comment">//指明版本号，修饰符，类名，包名，父类，接口</span></span><br><span class="line">                classWriter.visit(Opcodes.V1_8, Opcodes.ACC_PUBLIC, <span class="string">&quot;Class&quot;</span> + i, <span class="literal">null</span>, <span class="string">&quot;java/lang/Object&quot;</span>, <span class="literal">null</span>);</span><br><span class="line">                <span class="comment">//返回byte[]</span></span><br><span class="line">                <span class="type">byte</span>[] code = classWriter.toByteArray();</span><br><span class="line">                <span class="comment">//类的加载</span></span><br><span class="line">                test.defineClass(<span class="string">&quot;Class&quot;</span> + i, code, <span class="number">0</span>, code.length);<span class="comment">//Class对象</span></span><br><span class="line">                j++;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125; <span class="keyword">finally</span> &#123;</span><br><span class="line">            System.out.println(j);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure>



<p><strong>不设置元空间的上限</strong></p>
<p>使用默认的 JVM 参数，元空间不设置上限</p>
<p>输出结果：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="number">10000</span></span><br></pre></td></tr></table></figure>



<p><strong>设置元空间的上限</strong></p>
<p>JVM 参数</p>
<p>-XX:MetaspaceSize&#x3D;10m -XX:MaxMetaspaceSize&#x3D;10m</p>
<p>输出结果：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="number">8531</span></span><br><span class="line">Exception in thread <span class="string">&quot;main&quot;</span> java.lang.OutOfMemoryError: Metaspace</span><br><span class="line">	at java.lang.ClassLoader.defineClass1(Native Method)</span><br><span class="line">	at java.lang.ClassLoader.defineClass(ClassLoader.java:<span class="number">763</span>)</span><br><span class="line">	at java.lang.ClassLoader.defineClass(ClassLoader.java:<span class="number">642</span>)</span><br><span class="line">	at com.atguigu.java.OOMTest.main(OOMTest.java:<span class="number">29</span>)</span><br></pre></td></tr></table></figure>



<h3 id="如何解决OOM"><a href="#如何解决OOM" class="headerlink" title="如何解决OOM"></a>如何解决OOM</h3><blockquote>
<p>这个属于调优的问题，这里先简单的说一下</p>
</blockquote>
<ol>
<li>要解决OOM异常或heap space的异常，一般的手段是首先通过内存映像分析工具（如Ec1ipse Memory Analyzer）对dump出来的堆转储快照进行分析，重点是确认内存中的对象是否是必要的，也就是要先分清楚到底是出现了内存泄漏（Memory Leak）还是内存溢出（Memory Overflow）</li>
<li><strong>内存泄漏</strong>就是有大量的引用指向某些对象，但是这些对象以后不会使用了，但是因为它们还和GC ROOT有关联，所以导致以后这些对象也不会被回收，这就是内存泄漏的问题</li>
<li>如果是内存泄漏，可进一步通过工具查看泄漏对象到GC Roots的引用链。于是就能找到泄漏对象是通过怎样的路径与GC Roots相关联并导致垃圾收集器无法自动回收它们的。掌握了泄漏对象的类型信息，以及GC Roots引用链的信息，就可以比较准确地定位出泄漏代码的位置。</li>
<li>如果不存在内存泄漏，换句话说就是内存中的对象确实都还必须存活着，那就应当检查虚拟机的堆参数（-Xmx与-Xms），与机器物理内存对比看是否还可以调大，从代码上检查是否存在某些对象生命周期过长、持有状态时间过长的情况，尝试减少程序运行期的内存消耗。</li>
</ol>
<h2 id="方法区的内部结构"><a href="#方法区的内部结构" class="headerlink" title="方法区的内部结构"></a>方法区的内部结构</h2><h3 id="方法区存储什么？"><a href="#方法区存储什么？" class="headerlink" title="方法区存储什么？"></a>方法区存储什么？</h3><h4 id="概念"><a href="#概念" class="headerlink" title="概念"></a>概念</h4><img src="https://npm.elemecdn.com/youthlql@1.0.8/JVM/chapter_006/0007.png">

<p>《深入理解Java虚拟机》书中对方法区（Method Area）存储内容描述如下：它用于存储已被虚拟机加载的<strong>类型信息、常量、静态变量、即时编译器编译后的代码缓存</strong>等。</p>
<img src="https://npm.elemecdn.com/youthlql@1.0.8/JVM/chapter_006/0008.png">



<p><strong>类型信息</strong></p>
<p>对每个加载的类型（类class、接口interface、枚举enum、注解annotation），JVM必须在方法区中存储以下类型信息：</p>
<ol>
<li>这个类型的完整有效名称（全名&#x3D;包名.类名）</li>
<li>这个类型直接父类的完整有效名（对于interface或是java.lang.Object，都没有父类）</li>
<li>这个类型的修饰符（public，abstract，final的某个子集）</li>
<li>这个类型直接接口的一个有序列表</li>
</ol>
<p><strong>域（Field）信息</strong></p>
<blockquote>
<p>也就是我们常说的成员变量，域信息是比较官方的称呼</p>
</blockquote>
<ol>
<li><p>JVM必须在方法区中保存类型的所有域的相关信息以及域的声明顺序。</p>
</li>
<li><p>域的相关信息包括：域名称，域类型，域修饰符（public，private，protected，static，final，volatile，transient的某个子集）</p>
</li>
</ol>
<p><strong>方法（Method）信息</strong></p>
<p>JVM必须保存所有方法的以下信息，同域信息一样包括声明顺序：</p>
<ol>
<li>方法名称</li>
<li>方法的返回类型（包括 void 返回类型），void 在 Java 中对应的为 void.class</li>
<li>方法参数的数量和类型（按顺序）</li>
<li>方法的修饰符（public，private，protected，static，final，synchronized，native，abstract的一个子集）</li>
<li>方法的字节码（bytecodes）、操作数栈、局部变量表及大小（abstract和native方法除外）</li>
<li>异常表（abstract和native方法除外），异常表记录每个异常处理的开始位置、结束位置、代码处理在程序计数器中的偏移地址、被捕获的异常类的常量池索引</li>
</ol>
<h4 id="举例"><a href="#举例" class="headerlink" title="举例"></a>举例</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line">**</span><br><span class="line"> * 测试方法区的内部构成</span><br><span class="line"> */</span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">MethodInnerStrucTest</span> <span class="keyword">extends</span> <span class="title class_">Object</span> <span class="keyword">implements</span> <span class="title class_">Comparable</span>&lt;String&gt;,Serializable &#123;</span><br><span class="line">    <span class="comment">//属性</span></span><br><span class="line">    <span class="keyword">public</span> <span class="type">int</span> <span class="variable">num</span> <span class="operator">=</span> <span class="number">10</span>;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> <span class="type">String</span> <span class="variable">str</span> <span class="operator">=</span> <span class="string">&quot;测试方法的内部结构&quot;</span>;</span><br><span class="line">    <span class="comment">//构造器</span></span><br><span class="line">    <span class="comment">//方法</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">test1</span><span class="params">()</span>&#123;</span><br><span class="line">        <span class="type">int</span> <span class="variable">count</span> <span class="operator">=</span> <span class="number">20</span>;</span><br><span class="line">        System.out.println(<span class="string">&quot;count = &quot;</span> + count);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="type">int</span> <span class="title function_">test2</span><span class="params">(<span class="type">int</span> cal)</span>&#123;</span><br><span class="line">        <span class="type">int</span> <span class="variable">result</span> <span class="operator">=</span> <span class="number">0</span>;</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            <span class="type">int</span> <span class="variable">value</span> <span class="operator">=</span> <span class="number">30</span>;</span><br><span class="line">            result = value / cal;</span><br><span class="line">        &#125; <span class="keyword">catch</span> (Exception e) &#123;</span><br><span class="line">            e.printStackTrace();</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> result;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="type">int</span> <span class="title function_">compareTo</span><span class="params">(String o)</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure>



<p><code>javap -v -p MethodInnerStrucTest.class &gt; test.txt</code></p>
<ul>
<li>反编译字节码文件，并输出值文本文件中，便于查看。参数 -p 确保能查看 private 权限类型的字段或方法</li>
</ul>
<p>字节码：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br><span class="line">175</span><br><span class="line">176</span><br><span class="line">177</span><br><span class="line">178</span><br><span class="line">179</span><br><span class="line">180</span><br><span class="line">181</span><br><span class="line">182</span><br><span class="line">183</span><br><span class="line">184</span><br><span class="line">185</span><br><span class="line">186</span><br><span class="line">187</span><br><span class="line">188</span><br><span class="line">189</span><br><span class="line">190</span><br><span class="line">191</span><br><span class="line">192</span><br><span class="line">193</span><br><span class="line">194</span><br><span class="line">195</span><br><span class="line">196</span><br><span class="line">197</span><br><span class="line">198</span><br><span class="line">199</span><br><span class="line">200</span><br><span class="line">201</span><br><span class="line">202</span><br><span class="line">203</span><br><span class="line">204</span><br><span class="line">205</span><br><span class="line">206</span><br><span class="line">207</span><br><span class="line">208</span><br><span class="line">209</span><br><span class="line">210</span><br><span class="line">211</span><br><span class="line">212</span><br><span class="line">213</span><br><span class="line">214</span><br><span class="line">215</span><br><span class="line">216</span><br><span class="line">217</span><br><span class="line">218</span><br><span class="line">219</span><br><span class="line">220</span><br><span class="line">221</span><br><span class="line">222</span><br><span class="line">223</span><br><span class="line">224</span><br><span class="line">225</span><br><span class="line">226</span><br><span class="line">227</span><br><span class="line">228</span><br><span class="line">229</span><br><span class="line">230</span><br><span class="line">231</span><br><span class="line">232</span><br><span class="line">233</span><br><span class="line">234</span><br><span class="line">235</span><br><span class="line">236</span><br><span class="line">237</span><br></pre></td><td class="code"><pre><span class="line">Classfile /F:/IDEAWorkSpaceSourceCode/JVMDemo/out/production/chapter09/com/atguigu/java/MethodInnerStrucTest.<span class="keyword">class</span></span><br><span class="line">  <span class="title class_">Last</span> modified <span class="number">2020</span>-<span class="number">11</span>-<span class="number">13</span>; size <span class="number">1626</span> bytes</span><br><span class="line">  MD5 checksum 0d0fcb54854d4ce183063df985141ad0</span><br><span class="line">  Compiled from <span class="string">&quot;MethodInnerStrucTest.java&quot;</span></span><br><span class="line"><span class="comment">//类型信息      </span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">com</span>.atguigu.java.MethodInnerStrucTest <span class="keyword">extends</span> <span class="title class_">java</span>.lang.Object <span class="keyword">implements</span> <span class="title class_">java</span>.lang.Comparable&lt;java.lang.String&gt;, java.io.Serializable</span><br><span class="line">  minor version: <span class="number">0</span></span><br><span class="line">  major version: <span class="number">52</span></span><br><span class="line">  flags: ACC_PUBLIC, ACC_SUPER</span><br><span class="line">Constant pool:</span><br><span class="line">   #<span class="number">1</span> = Methodref          #<span class="number">18.</span>#<span class="number">52</span>        <span class="comment">// java/lang/Object.&quot;&lt;init&gt;&quot;:()V</span></span><br><span class="line">   #<span class="number">2</span> = Fieldref           #<span class="number">17.</span>#<span class="number">53</span>        <span class="comment">// com/atguigu/java/MethodInnerStrucTest.num:I</span></span><br><span class="line">   #<span class="number">3</span> = Fieldref           #<span class="number">54.</span>#<span class="number">55</span>        <span class="comment">// java/lang/System.out:Ljava/io/PrintStream;</span></span><br><span class="line">   #<span class="number">4</span> = Class              #<span class="number">56</span>            <span class="comment">// java/lang/StringBuilder</span></span><br><span class="line">   #<span class="number">5</span> = Methodref          #<span class="number">4.</span>#<span class="number">52</span>         <span class="comment">// java/lang/StringBuilder.&quot;&lt;init&gt;&quot;:()V</span></span><br><span class="line">   #<span class="number">6</span> = String             #<span class="number">57</span>            <span class="comment">// count =</span></span><br><span class="line">   #<span class="number">7</span> = Methodref          #<span class="number">4.</span>#<span class="number">58</span>         <span class="comment">// java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;</span></span><br><span class="line">   #<span class="number">8</span> = Methodref          #<span class="number">4.</span>#<span class="number">59</span>         <span class="comment">// java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;</span></span><br><span class="line">   #<span class="number">9</span> = Methodref          #<span class="number">4.</span>#<span class="number">60</span>         <span class="comment">// java/lang/StringBuilder.toString:()Ljava/lang/String;</span></span><br><span class="line">  #<span class="number">10</span> = Methodref          #<span class="number">61.</span>#<span class="number">62</span>        <span class="comment">// java/io/PrintStream.println:(Ljava/lang/String;)V</span></span><br><span class="line">  #<span class="number">11</span> = Class              #<span class="number">63</span>            <span class="comment">// java/lang/Exception</span></span><br><span class="line">  #<span class="number">12</span> = Methodref          #<span class="number">11.</span>#<span class="number">64</span>        <span class="comment">// java/lang/Exception.printStackTrace:()V</span></span><br><span class="line">  #<span class="number">13</span> = Class              #<span class="number">65</span>            <span class="comment">// java/lang/String</span></span><br><span class="line">  #<span class="number">14</span> = Methodref          #<span class="number">17.</span>#<span class="number">66</span>        <span class="comment">// com/atguigu/java/MethodInnerStrucTest.compareTo:(Ljava/lang/String;)I</span></span><br><span class="line">  #<span class="number">15</span> = String             #<span class="number">67</span>            <span class="comment">// 测试方法的内部结构</span></span><br><span class="line">  #<span class="number">16</span> = Fieldref           #<span class="number">17.</span>#<span class="number">68</span>        <span class="comment">// com/atguigu/java/MethodInnerStrucTest.str:Ljava/lang/String;</span></span><br><span class="line">  #<span class="number">17</span> = Class              #<span class="number">69</span>            <span class="comment">// com/atguigu/java/MethodInnerStrucTest</span></span><br><span class="line">  #<span class="number">18</span> = Class              #<span class="number">70</span>            <span class="comment">// java/lang/Object</span></span><br><span class="line">  #<span class="number">19</span> = Class              #<span class="number">71</span>            <span class="comment">// java/lang/Comparable</span></span><br><span class="line">  #<span class="number">20</span> = Class              #<span class="number">72</span>            <span class="comment">// java/io/Serializable</span></span><br><span class="line">  #<span class="number">21</span> = Utf8               num</span><br><span class="line">  #<span class="number">22</span> = Utf8               I</span><br><span class="line">  #<span class="number">23</span> = Utf8               str</span><br><span class="line">  #<span class="number">24</span> = Utf8               Ljava/lang/String;</span><br><span class="line">  #<span class="number">25</span> = Utf8               &lt;init&gt;</span><br><span class="line">  #<span class="number">26</span> = Utf8               ()V</span><br><span class="line">  #<span class="number">27</span> = Utf8               Code</span><br><span class="line">  #<span class="number">28</span> = Utf8               LineNumberTable</span><br><span class="line">  #<span class="number">29</span> = Utf8               LocalVariableTable</span><br><span class="line">  #<span class="number">30</span> = Utf8               <span class="built_in">this</span></span><br><span class="line">  #<span class="number">31</span> = Utf8               Lcom/atguigu/java/MethodInnerStrucTest;</span><br><span class="line">  #<span class="number">32</span> = Utf8               test1</span><br><span class="line">  #<span class="number">33</span> = Utf8               count</span><br><span class="line">  #<span class="number">34</span> = Utf8               test2</span><br><span class="line">  #<span class="number">35</span> = Utf8               (I)I</span><br><span class="line">  #<span class="number">36</span> = Utf8               value</span><br><span class="line">  #<span class="number">37</span> = Utf8               e</span><br><span class="line">  #<span class="number">38</span> = Utf8               Ljava/lang/Exception;</span><br><span class="line">  #<span class="number">39</span> = Utf8               cal</span><br><span class="line">  #<span class="number">40</span> = Utf8               result</span><br><span class="line">  #<span class="number">41</span> = Utf8               StackMapTable</span><br><span class="line">  #<span class="number">42</span> = Class              #<span class="number">63</span>            <span class="comment">// java/lang/Exception</span></span><br><span class="line">  #<span class="number">43</span> = Utf8               compareTo</span><br><span class="line">  #<span class="number">44</span> = Utf8               (Ljava/lang/String;)I</span><br><span class="line">  #<span class="number">45</span> = Utf8               o</span><br><span class="line">  #<span class="number">46</span> = Utf8               (Ljava/lang/Object;)I</span><br><span class="line">  #<span class="number">47</span> = Utf8               &lt;clinit&gt;</span><br><span class="line">  #<span class="number">48</span> = Utf8               Signature</span><br><span class="line">  #<span class="number">49</span> = Utf8               Ljava/lang/Object;Ljava/lang/Comparable&lt;Ljava/lang/String;&gt;;Ljava/io/Serializable;</span><br><span class="line">  #<span class="number">50</span> = Utf8               SourceFile</span><br><span class="line">  #<span class="number">51</span> = Utf8               MethodInnerStrucTest.java</span><br><span class="line">  #<span class="number">52</span> = NameAndType        #<span class="number">25</span>:#<span class="number">26</span>        <span class="comment">// &quot;&lt;init&gt;&quot;:()V</span></span><br><span class="line">  #<span class="number">53</span> = NameAndType        #<span class="number">21</span>:#<span class="number">22</span>        <span class="comment">// num:I</span></span><br><span class="line">  #<span class="number">54</span> = Class              #<span class="number">73</span>            <span class="comment">// java/lang/System</span></span><br><span class="line">  #<span class="number">55</span> = NameAndType        #<span class="number">74</span>:#<span class="number">75</span>        <span class="comment">// out:Ljava/io/PrintStream;</span></span><br><span class="line">  #<span class="number">56</span> = Utf8               java/lang/StringBuilder</span><br><span class="line">  #<span class="number">57</span> = <span class="type">Utf8</span>               <span class="variable">count</span> <span class="operator">=</span></span><br><span class="line">  #<span class="number">58</span> = NameAndType        #<span class="number">76</span>:#<span class="number">77</span>        <span class="comment">// append:(Ljava/lang/String;)Ljava/lang/StringBuilder;</span></span><br><span class="line">  #<span class="number">59</span> = NameAndType        #<span class="number">76</span>:#<span class="number">78</span>        <span class="comment">// append:(I)Ljava/lang/StringBuilder;</span></span><br><span class="line">  #<span class="number">60</span> = NameAndType        #<span class="number">79</span>:#<span class="number">80</span>        <span class="comment">// toString:()Ljava/lang/String;</span></span><br><span class="line">  #<span class="number">61</span> = Class              #<span class="number">81</span>            <span class="comment">// java/io/PrintStream</span></span><br><span class="line">  #<span class="number">62</span> = NameAndType        #<span class="number">82</span>:#<span class="number">83</span>        <span class="comment">// println:(Ljava/lang/String;)V</span></span><br><span class="line">  #<span class="number">63</span> = Utf8               java/lang/Exception</span><br><span class="line">  #<span class="number">64</span> = NameAndType        #<span class="number">84</span>:#<span class="number">26</span>        <span class="comment">// printStackTrace:()V</span></span><br><span class="line">  #<span class="number">65</span> = Utf8               java/lang/String</span><br><span class="line">  #<span class="number">66</span> = NameAndType        #<span class="number">43</span>:#<span class="number">44</span>        <span class="comment">// compareTo:(Ljava/lang/String;)I</span></span><br><span class="line">  #<span class="number">67</span> = Utf8               测试方法的内部结构</span><br><span class="line">  #<span class="number">68</span> = NameAndType        #<span class="number">23</span>:#<span class="number">24</span>        <span class="comment">// str:Ljava/lang/String;</span></span><br><span class="line">  #<span class="number">69</span> = Utf8               com/atguigu/java/MethodInnerStrucTest</span><br><span class="line">  #<span class="number">70</span> = Utf8               java/lang/Object</span><br><span class="line">  #<span class="number">71</span> = Utf8               java/lang/Comparable</span><br><span class="line">  #<span class="number">72</span> = Utf8               java/io/Serializable</span><br><span class="line">  #<span class="number">73</span> = Utf8               java/lang/System</span><br><span class="line">  #<span class="number">74</span> = Utf8               out</span><br><span class="line">  #<span class="number">75</span> = Utf8               Ljava/io/PrintStream;</span><br><span class="line">  #<span class="number">76</span> = Utf8               append</span><br><span class="line">  #<span class="number">77</span> = Utf8               (Ljava/lang/String;)Ljava/lang/StringBuilder;</span><br><span class="line">  #<span class="number">78</span> = Utf8               (I)Ljava/lang/StringBuilder;</span><br><span class="line">  #<span class="number">79</span> = Utf8               toString</span><br><span class="line">  #<span class="number">80</span> = Utf8               ()Ljava/lang/String;</span><br><span class="line">  #<span class="number">81</span> = Utf8               java/io/PrintStream</span><br><span class="line">  #<span class="number">82</span> = Utf8               println</span><br><span class="line">  #<span class="number">83</span> = Utf8               (Ljava/lang/String;)V</span><br><span class="line">  #<span class="number">84</span> = Utf8               printStackTrace</span><br><span class="line">&#123;</span><br><span class="line"><span class="comment">//域信息</span></span><br><span class="line">  <span class="keyword">public</span> <span class="type">int</span> num;</span><br><span class="line">    descriptor: I</span><br><span class="line">    flags: ACC_PUBLIC</span><br><span class="line"></span><br><span class="line">  <span class="keyword">private</span> <span class="keyword">static</span> java.lang.String str;</span><br><span class="line">    descriptor: Ljava/lang/String;</span><br><span class="line">    flags: ACC_PRIVATE, ACC_STATIC</span><br><span class="line"></span><br><span class="line">  <span class="comment">//方法信息</span></span><br><span class="line">  <span class="keyword">public</span> com.atguigu.java.MethodInnerStrucTest();</span><br><span class="line">    descriptor: ()V</span><br><span class="line">    flags: ACC_PUBLIC</span><br><span class="line">    Code:</span><br><span class="line">      stack=<span class="number">2</span>, locals=<span class="number">1</span>, args_size=<span class="number">1</span></span><br><span class="line">         <span class="number">0</span>: aload_0</span><br><span class="line">         <span class="number">1</span>: invokespecial #<span class="number">1</span>                  <span class="comment">// Method java/lang/Object.&quot;&lt;init&gt;&quot;:()V</span></span><br><span class="line">         <span class="number">4</span>: aload_0</span><br><span class="line">         <span class="number">5</span>: bipush        <span class="number">10</span></span><br><span class="line">         <span class="number">7</span>: putfield      #<span class="number">2</span>                  <span class="comment">// Field num:I</span></span><br><span class="line">        <span class="number">10</span>: <span class="keyword">return</span></span><br><span class="line">      LineNumberTable:</span><br><span class="line">        line <span class="number">10</span>: <span class="number">0</span></span><br><span class="line">        line <span class="number">12</span>: <span class="number">4</span></span><br><span class="line">      LocalVariableTable:</span><br><span class="line">        Start  Length  Slot  Name   Signature</span><br><span class="line">            <span class="number">0</span>      <span class="number">11</span>     <span class="number">0</span>  <span class="built_in">this</span>   Lcom/atguigu/java/MethodInnerStrucTest;</span><br><span class="line"></span><br><span class="line">  <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">test1</span><span class="params">()</span>;</span><br><span class="line">    descriptor: ()V</span><br><span class="line">    flags: ACC_PUBLIC</span><br><span class="line">    Code:</span><br><span class="line">      stack=<span class="number">3</span>, locals=<span class="number">2</span>, args_size=<span class="number">1</span></span><br><span class="line">         <span class="number">0</span>: bipush        <span class="number">20</span></span><br><span class="line">         <span class="number">2</span>: istore_1</span><br><span class="line">         <span class="number">3</span>: getstatic     #<span class="number">3</span>                  <span class="comment">// Field java/lang/System.out:Ljava/io/PrintStream;</span></span><br><span class="line">         <span class="number">6</span>: <span class="keyword">new</span>           #<span class="number">4</span>                  <span class="comment">// class java/lang/StringBuilder</span></span><br><span class="line">         <span class="number">9</span>: dup</span><br><span class="line">        <span class="number">10</span>: invokespecial #<span class="number">5</span>                  <span class="comment">// Method java/lang/StringBuilder.&quot;&lt;init&gt;&quot;:()V</span></span><br><span class="line">        <span class="number">13</span>: ldc           #<span class="number">6</span>                  <span class="comment">// String count =</span></span><br><span class="line">        <span class="number">15</span>: invokevirtual #<span class="number">7</span>                  <span class="comment">// Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;</span></span><br><span class="line">        <span class="number">18</span>: iload_1</span><br><span class="line">        <span class="number">19</span>: invokevirtual #<span class="number">8</span>                  <span class="comment">// Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;</span></span><br><span class="line">        <span class="number">22</span>: invokevirtual #<span class="number">9</span>                  <span class="comment">// Method java/lang/StringBuilder.toString:()Ljava/lang/String;</span></span><br><span class="line">        <span class="number">25</span>: invokevirtual #<span class="number">10</span>                 <span class="comment">// Method java/io/PrintStream.println:(Ljava/lang/String;)V</span></span><br><span class="line">        <span class="number">28</span>: <span class="keyword">return</span></span><br><span class="line">      LineNumberTable:</span><br><span class="line">        line <span class="number">17</span>: <span class="number">0</span></span><br><span class="line">        line <span class="number">18</span>: <span class="number">3</span></span><br><span class="line">        line <span class="number">19</span>: <span class="number">28</span></span><br><span class="line">      LocalVariableTable:</span><br><span class="line">        Start  Length  Slot  Name   Signature</span><br><span class="line">            <span class="number">0</span>      <span class="number">29</span>     <span class="number">0</span>  <span class="built_in">this</span>   Lcom/atguigu/java/MethodInnerStrucTest;</span><br><span class="line">            <span class="number">3</span>      <span class="number">26</span>     <span class="number">1</span> count   I</span><br><span class="line"></span><br><span class="line">  <span class="keyword">public</span> <span class="keyword">static</span> <span class="type">int</span> <span class="title function_">test2</span><span class="params">(<span class="type">int</span>)</span>;</span><br><span class="line">    descriptor: (I)I</span><br><span class="line">    flags: ACC_PUBLIC, ACC_STATIC</span><br><span class="line">    Code:</span><br><span class="line">      stack=<span class="number">2</span>, locals=<span class="number">3</span>, args_size=<span class="number">1</span></span><br><span class="line">         <span class="number">0</span>: iconst_0</span><br><span class="line">         <span class="number">1</span>: istore_1</span><br><span class="line">         <span class="number">2</span>: bipush        <span class="number">30</span></span><br><span class="line">         <span class="number">4</span>: istore_2</span><br><span class="line">         <span class="number">5</span>: iload_2</span><br><span class="line">         <span class="number">6</span>: iload_0</span><br><span class="line">         <span class="number">7</span>: idiv</span><br><span class="line">         <span class="number">8</span>: istore_1</span><br><span class="line">         <span class="number">9</span>: goto          <span class="number">17</span></span><br><span class="line">        <span class="number">12</span>: astore_2</span><br><span class="line">        <span class="number">13</span>: aload_2</span><br><span class="line">        <span class="number">14</span>: invokevirtual #<span class="number">12</span>                 <span class="comment">// Method java/lang/Exception.printStackTrace:()V</span></span><br><span class="line">        <span class="number">17</span>: iload_1</span><br><span class="line">        <span class="number">18</span>: ireturn</span><br><span class="line">      Exception table:</span><br><span class="line">         from    to  target type</span><br><span class="line">             <span class="number">2</span>     <span class="number">9</span>    <span class="number">12</span>   Class java/lang/Exception</span><br><span class="line">      LineNumberTable:</span><br><span class="line">        line <span class="number">21</span>: <span class="number">0</span></span><br><span class="line">        line <span class="number">23</span>: <span class="number">2</span></span><br><span class="line">        line <span class="number">24</span>: <span class="number">5</span></span><br><span class="line">        line <span class="number">27</span>: <span class="number">9</span></span><br><span class="line">        line <span class="number">25</span>: <span class="number">12</span></span><br><span class="line">        line <span class="number">26</span>: <span class="number">13</span></span><br><span class="line">        line <span class="number">28</span>: <span class="number">17</span></span><br><span class="line">      LocalVariableTable:</span><br><span class="line">        Start  Length  Slot  Name   Signature</span><br><span class="line">            <span class="number">5</span>       <span class="number">4</span>     <span class="number">2</span> value   I</span><br><span class="line">           <span class="number">13</span>       <span class="number">4</span>     <span class="number">2</span>     e   Ljava/lang/Exception;</span><br><span class="line">            <span class="number">0</span>      <span class="number">19</span>     <span class="number">0</span>   cal   I</span><br><span class="line">            <span class="number">2</span>      <span class="number">17</span>     <span class="number">1</span> result   I</span><br><span class="line">      StackMapTable: number_of_entries = <span class="number">2</span></span><br><span class="line">        frame_type = <span class="number">255</span> <span class="comment">/* full_frame */</span></span><br><span class="line">          offset_delta = <span class="number">12</span></span><br><span class="line">          locals = [ <span class="type">int</span>, <span class="type">int</span> ]</span><br><span class="line">          stack = [ <span class="keyword">class</span> <span class="title class_">java</span>/lang/Exception ]</span><br><span class="line">        frame_type = <span class="number">4</span> <span class="comment">/* same */</span></span><br><span class="line"></span><br><span class="line">  <span class="keyword">public</span> <span class="type">int</span> <span class="title function_">compareTo</span><span class="params">(java.lang.String)</span>;</span><br><span class="line">    descriptor: (Ljava/lang/String;)I</span><br><span class="line">    flags: ACC_PUBLIC</span><br><span class="line">    Code:</span><br><span class="line">      stack=<span class="number">1</span>, locals=<span class="number">2</span>, args_size=<span class="number">2</span></span><br><span class="line">         <span class="number">0</span>: iconst_0</span><br><span class="line">         <span class="number">1</span>: ireturn</span><br><span class="line">      LineNumberTable:</span><br><span class="line">        line <span class="number">33</span>: <span class="number">0</span></span><br><span class="line">      LocalVariableTable:</span><br><span class="line">        Start  Length  Slot  Name   Signature</span><br><span class="line">            <span class="number">0</span>       <span class="number">2</span>     <span class="number">0</span>  <span class="built_in">this</span>   Lcom/atguigu/java/MethodInnerStrucTest;</span><br><span class="line">            <span class="number">0</span>       <span class="number">2</span>     <span class="number">1</span>     o   Ljava/lang/String;</span><br><span class="line"></span><br><span class="line">  <span class="keyword">public</span> <span class="type">int</span> <span class="title function_">compareTo</span><span class="params">(java.lang.Object)</span>;</span><br><span class="line">    descriptor: (Ljava/lang/Object;)I</span><br><span class="line">    flags: ACC_PUBLIC, ACC_BRIDGE, ACC_SYNTHETIC</span><br><span class="line">    Code:</span><br><span class="line">      stack=<span class="number">2</span>, locals=<span class="number">2</span>, args_size=<span class="number">2</span></span><br><span class="line">         <span class="number">0</span>: aload_0</span><br><span class="line">         <span class="number">1</span>: aload_1</span><br><span class="line">         <span class="number">2</span>: checkcast     #<span class="number">13</span>                 <span class="comment">// class java/lang/String</span></span><br><span class="line">         <span class="number">5</span>: invokevirtual #<span class="number">14</span>                 <span class="comment">// Method compareTo:(Ljava/lang/String;)I</span></span><br><span class="line">         <span class="number">8</span>: ireturn</span><br><span class="line">      LineNumberTable:</span><br><span class="line">        line <span class="number">10</span>: <span class="number">0</span></span><br><span class="line">      LocalVariableTable:</span><br><span class="line">        Start  Length  Slot  Name   Signature</span><br><span class="line">            <span class="number">0</span>       <span class="number">9</span>     <span class="number">0</span>  <span class="built_in">this</span>   Lcom/atguigu/java/MethodInnerStrucTest;</span><br><span class="line"></span><br><span class="line">  <span class="keyword">static</span> &#123;&#125;;</span><br><span class="line">    descriptor: ()V</span><br><span class="line">    flags: ACC_STATIC</span><br><span class="line">    Code:</span><br><span class="line">      stack=<span class="number">1</span>, locals=<span class="number">0</span>, args_size=<span class="number">0</span></span><br><span class="line">         <span class="number">0</span>: ldc           #<span class="number">15</span>                 <span class="comment">// String 测试方法的内部结构</span></span><br><span class="line">         <span class="number">2</span>: putstatic     #<span class="number">16</span>                 <span class="comment">// Field str:Ljava/lang/String;</span></span><br><span class="line">         <span class="number">5</span>: <span class="keyword">return</span></span><br><span class="line">      LineNumberTable:</span><br><span class="line">        line <span class="number">13</span>: <span class="number">0</span></span><br><span class="line">&#125;</span><br><span class="line">Signature: #<span class="number">49</span>                          <span class="comment">// Ljava/lang/Object;Ljava/lang/Comparable&lt;Ljava/lang/String;&gt;;Ljava/io/Serializable;</span></span><br><span class="line">SourceFile: <span class="string">&quot;MethodInnerStrucTest.java&quot;</span></span><br><span class="line"></span><br></pre></td></tr></table></figure>



<p><strong>类型信息</strong></p>
<p>在运行时方法区中，类信息中记录了哪个加载器加载了该类，同时类加载器也记录了它加载了哪些类</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//类型信息      </span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">com</span>.atguigu.java.MethodInnerStrucTest <span class="keyword">extends</span> <span class="title class_">java</span>.lang.Object <span class="keyword">implements</span> <span class="title class_">java</span>.lang.Comparable&lt;java.lang.String&gt;, java.io.Serializable</span><br></pre></td></tr></table></figure>





<p><strong>域信息</strong></p>
<ol>
<li>descriptor: I 表示字段类型为 Integer</li>
<li>flags: ACC_PUBLIC 表示字段权限修饰符为 public</li>
</ol>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//域信息</span></span><br><span class="line">  <span class="keyword">public</span> <span class="type">int</span> num;</span><br><span class="line">    descriptor: I</span><br><span class="line">    flags: ACC_PUBLIC</span><br><span class="line"></span><br><span class="line">  <span class="keyword">private</span> <span class="keyword">static</span> java.lang.String str;</span><br><span class="line">    descriptor: Ljava/lang/String;</span><br><span class="line">    flags: ACC_PRIVATE, ACC_STATIC</span><br></pre></td></tr></table></figure>





<p><strong>方法信息</strong></p>
<ol>
<li>descriptor: ()V 表示方法返回值类型为 void</li>
<li>flags: ACC_PUBLIC 表示方法权限修饰符为 public</li>
<li>stack&#x3D;3 表示操作数栈深度为 3</li>
<li>locals&#x3D;2 表示局部变量个数为 2 个（实力方法包含 this）</li>
<li>test1() 方法虽然没有参数，但是其 args_size&#x3D;1 ，这时因为将 this 作为了参数</li>
</ol>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">test1</span><span class="params">()</span>;</span><br><span class="line">    descriptor: ()V</span><br><span class="line">    flags: ACC_PUBLIC</span><br><span class="line">    Code:</span><br><span class="line">      stack=<span class="number">3</span>, locals=<span class="number">2</span>, args_size=<span class="number">1</span></span><br><span class="line">         <span class="number">0</span>: bipush        <span class="number">20</span></span><br><span class="line">         <span class="number">2</span>: istore_1</span><br><span class="line">         <span class="number">3</span>: getstatic     #<span class="number">3</span>                  <span class="comment">// Field java/lang/System.out:Ljava/io/PrintStream;</span></span><br><span class="line">         <span class="number">6</span>: <span class="keyword">new</span>           #<span class="number">4</span>                  <span class="comment">// class java/lang/StringBuilder</span></span><br><span class="line">         <span class="number">9</span>: dup</span><br><span class="line">        <span class="number">10</span>: invokespecial #<span class="number">5</span>                  <span class="comment">// Method java/lang/StringBuilder.&quot;&lt;init&gt;&quot;:()V</span></span><br><span class="line">        <span class="number">13</span>: ldc           #<span class="number">6</span>                  <span class="comment">// String count =</span></span><br><span class="line">        <span class="number">15</span>: invokevirtual #<span class="number">7</span>                  <span class="comment">// Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;</span></span><br><span class="line">        <span class="number">18</span>: iload_1</span><br><span class="line">        <span class="number">19</span>: invokevirtual #<span class="number">8</span>                  <span class="comment">// Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;</span></span><br><span class="line">        <span class="number">22</span>: invokevirtual #<span class="number">9</span>                  <span class="comment">// Method java/lang/StringBuilder.toString:()Ljava/lang/String;</span></span><br><span class="line">        <span class="number">25</span>: invokevirtual #<span class="number">10</span>                 <span class="comment">// Method java/io/PrintStream.println:(Ljava/lang/String;)V</span></span><br><span class="line">        <span class="number">28</span>: <span class="keyword">return</span></span><br><span class="line">      LineNumberTable:</span><br><span class="line">        line <span class="number">17</span>: <span class="number">0</span></span><br><span class="line">        line <span class="number">18</span>: <span class="number">3</span></span><br><span class="line">        line <span class="number">19</span>: <span class="number">28</span></span><br><span class="line">      LocalVariableTable:</span><br><span class="line">        Start  Length  Slot  Name   Signature</span><br><span class="line">            <span class="number">0</span>      <span class="number">29</span>     <span class="number">0</span>  <span class="built_in">this</span>   Lcom/atguigu/java/MethodInnerStrucTest;</span><br><span class="line">            <span class="number">3</span>      <span class="number">26</span>     <span class="number">1</span> count   I</span><br><span class="line"></span><br></pre></td></tr></table></figure>



<h3 id="non-final-类型的类变量"><a href="#non-final-类型的类变量" class="headerlink" title="non-final 类型的类变量"></a>non-final 类型的类变量</h3><ol>
<li><p>静态变量和类关联在一起，随着类的加载而加载，他们成为类数据在逻辑上的一部分</p>
</li>
<li><p>类变量被类的所有实例共享，即使没有类实例时，你也可以访问它</p>
</li>
</ol>
<p><strong>举例</strong></p>
<ol>
<li>如下代码所示，即使我们把order设置为null，也不会出现空指针异常</li>
<li>这更加表明了 static 类型的字段和方法随着类的加载而加载，并不属于特定的类实例</li>
</ol>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">MethodAreaTest</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">        <span class="type">Order</span> <span class="variable">order</span> <span class="operator">=</span> <span class="literal">null</span>;</span><br><span class="line">        order.hello();</span><br><span class="line">        System.out.println(order.count);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Order</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="type">int</span> <span class="variable">count</span> <span class="operator">=</span> <span class="number">1</span>;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="type">int</span> <span class="variable">number</span> <span class="operator">=</span> <span class="number">2</span>;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">hello</span><span class="params">()</span> &#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;hello!&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>输出结果：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">hello!</span><br><span class="line">1</span><br></pre></td></tr></table></figure>



<h4 id="全局常量：static-final"><a href="#全局常量：static-final" class="headerlink" title="全局常量：static final"></a>全局常量：static final</h4><ol>
<li><p>全局常量就是使用 static final 进行修饰</p>
</li>
<li><p>被声明为final的类变量的处理方法则不同，每个全局常量在编译的时候就会被分配了。</p>
</li>
</ol>
<p>查看上面代码，这部分的字节码指令</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">Order</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="type">int</span> <span class="variable">count</span> <span class="operator">=</span> <span class="number">1</span>;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="type">int</span> <span class="variable">number</span> <span class="operator">=</span> <span class="number">2</span>;</span><br><span class="line">    ...</span><br><span class="line">&#125;    </span><br></pre></td></tr></table></figure>



<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">static</span> <span class="type">int</span> count;</span><br><span class="line">    descriptor: I</span><br><span class="line">    flags: ACC_PUBLIC, ACC_STATIC</span><br><span class="line"></span><br><span class="line">  <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="type">int</span> number;</span><br><span class="line">    descriptor: I</span><br><span class="line">    flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL</span><br><span class="line">    ConstantValue: <span class="type">int</span> <span class="number">2</span></span><br></pre></td></tr></table></figure>

<p>可以发现 staitc和final同时修饰的number 的值在编译上的时候已经写死在字节码文件中了。</p>
<h3 id="运行时常量池"><a href="#运行时常量池" class="headerlink" title="运行时常量池"></a>运行时常量池</h3><h4 id="运行时常量池-VS-常量池"><a href="#运行时常量池-VS-常量池" class="headerlink" title="运行时常量池 VS 常量池"></a>运行时常量池 VS 常量池</h4><blockquote>
<p><strong>官方文档</strong>：<a target="_blank" rel="noopener" href="https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html">https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html</a></p>
<p>后面会细讲常量池，这里为了讲清楚方法区，简单带一下。</p>
</blockquote>
<img src="https://npm.elemecdn.com/youthlql@1.0.8/JVM/chapter_006/0009.png">

<ol>
<li>方法区，内部包含了运行时常量池</li>
<li>字节码文件，内部包含了常量池。（之前的字节码文件中已经看到了很多Constant pool的东西，这个就是常量池）</li>
<li>要弄清楚方法区，需要理解清楚ClassFile，因为加载类的信息都在方法区。</li>
<li>要弄清楚方法区的运行时常量池，需要理解清楚ClassFile中的常量池。</li>
</ol>
<h4 id="常量池"><a href="#常量池" class="headerlink" title="常量池"></a>常量池</h4><ol>
<li>一个有效的字节码文件中除了包含类的版本信息、字段、方法以及接口等描述符信息外。还包含一项信息就是<strong>常量池表</strong>（<strong>Constant Pool Table</strong>），包括各种字面量和对类型、域和方法的符号引用。</li>
<li>字面量： 10 ， “我是某某”这种数字和字符串都是字面量</li>
</ol>
<img src="https://npm.elemecdn.com/youthlql@1.0.8/JVM/chapter_006/0010.png">

<p><strong>为什么需要常量池？</strong></p>
<ol>
<li>一个java源文件中的类、接口，编译后产生一个字节码文件。而Java中的字节码需要数据支持，通常这种数据会很大以至于不能直接存到字节码里，换另一种方式，可以存到常量池。这个字节码包含了指向常量池的引用。在动态链接的时候会用到运行时常量池，之前有介绍</li>
</ol>
<p>比如：如下的代码：</p>
<pre><code>public class SimpleClass &#123;
    public void sayHello() &#123;
        System.out.println(&quot;hello&quot;);
    &#125;
&#125;
</code></pre>
<ol>
<li>虽然上述代码只有194字节，但是里面却使用了String、System、PrintStream及Object等结构。</li>
<li>比如说我们这个文件中有6个地方用到了”hello”这个字符串，如果不用常量池，就需要在6个地方全写一遍，造成臃肿。我们可以将”hello”等所需用到的结构信息记录在常量池中，并通过<strong>引用的方式</strong>，来加载、调用所需的结构</li>
<li>这里的代码量其实很少了，如果代码多的话，引用的结构将会更多，这里就需要用到常量池了。</li>
</ol>
<img src="https://npm.elemecdn.com/youthlql@1.0.8/JVM/chapter_006/0011.png">

<p><strong>常量池中有啥？</strong></p>
<ol>
<li>数量值</li>
<li>字符串值</li>
<li>类引用</li>
<li>字段引用</li>
<li>方法引用</li>
</ol>
<p>MethodInnerStrucTest 的 test1方法的字节码</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"> <span class="number">0</span> bipush <span class="number">20</span></span><br><span class="line"> <span class="number">2</span> istore_1</span><br><span class="line"> <span class="number">3</span> getstatic #<span class="number">3</span> &lt;java/lang/System.out&gt;</span><br><span class="line"> <span class="number">6</span> <span class="keyword">new</span> #<span class="number">4</span> &lt;java/lang/StringBuilder&gt;</span><br><span class="line"> <span class="number">9</span> dup</span><br><span class="line"><span class="number">10</span> invokespecial #<span class="number">5</span> &lt;java/lang/StringBuilder.&lt;init&gt;&gt;</span><br><span class="line"><span class="number">13</span> ldc #<span class="number">6</span> &lt;count = &gt;</span><br><span class="line"><span class="number">15</span> invokevirtual #<span class="number">7</span> &lt;java/lang/StringBuilder.append&gt;</span><br><span class="line"><span class="number">18</span> iload_1</span><br><span class="line"><span class="number">19</span> invokevirtual #<span class="number">8</span> &lt;java/lang/StringBuilder.append&gt;</span><br><span class="line"><span class="number">22</span> invokevirtual #<span class="number">9</span> &lt;java/lang/StringBuilder.toString&gt;</span><br><span class="line"><span class="number">25</span> invokevirtual #<span class="number">10</span> &lt;java/io/PrintStream.println&gt;</span><br><span class="line"><span class="number">28</span> <span class="keyword">return</span></span><br></pre></td></tr></table></figure>

<p>1、#3，#5等等这些带# 的，都是引用了常量池。</p>
<p><strong>常量池总结</strong></p>
<p>常量池、可以看做是一张表，虚拟机指令根据这张常量表找到要执行的类名、方法名、参数类型、字面量等类型。</p>
<h4 id="运行时常量池-1"><a href="#运行时常量池-1" class="headerlink" title="运行时常量池"></a>运行时常量池</h4><ol>
<li>运行时常量池（Runtime Constant Pool）是方法区的一部分。</li>
<li>常量池表（Constant Pool Table）是Class字节码文件的一部分，用于存放编译期生成的各种字面量与符号引用，<strong>这部分内容将在类加载后存放到方法区的运行时常量池中</strong>。（运行时常量池就是常量池在程序运行时的称呼）</li>
<li>运行时常量池，在加载类和接口到虚拟机后，就会创建对应的运行时常量池。</li>
<li>JVM为每个已加载的类型（类或接口）都维护一个常量池。池中的数据项像数组项一样，是通过索引访问的。</li>
<li>运行时常量池中包含多种不同的常量，包括编译期就已经明确的数值字面量，也包括到运行期解析后才能够获得的方法或者字段引用。<strong>此时不再是常量池中的符号地址了，这里换为真实地址</strong>。</li>
</ol>
<ul>
<li>运行时常量池，相对于Class文件常量池的另一重要特征是：具备动态性。</li>
</ul>
<ol start="6">
<li>运行时常量池类似于传统编程语言中的符号表（symbol table），但是它所包含的数据却比符号表要更加丰富一些。</li>
<li>当创建类或接口的运行时常量池时，如果构造运行时常量池所需的内存空间超过了方法区所能提供的最大值，则JVM会抛OutofMemoryError异常。</li>
</ol>
<h2 id="方法区的使用举例"><a href="#方法区的使用举例" class="headerlink" title="方法区的使用举例"></a>方法区的使用举例</h2><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">MethodAreaDemo</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">        <span class="type">int</span> <span class="variable">x</span> <span class="operator">=</span> <span class="number">500</span>;</span><br><span class="line">        <span class="type">int</span> <span class="variable">y</span> <span class="operator">=</span> <span class="number">100</span>;</span><br><span class="line">        <span class="type">int</span> <span class="variable">a</span> <span class="operator">=</span> x / y;</span><br><span class="line">        <span class="type">int</span> <span class="variable">b</span> <span class="operator">=</span> <span class="number">50</span>;</span><br><span class="line">        System.out.println(a + b);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<p>字节码</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">com</span>.atguigu.java1.MethodAreaDemo</span><br><span class="line">  minor version: <span class="number">0</span></span><br><span class="line">  major version: <span class="number">51</span></span><br><span class="line">  flags: ACC_PUBLIC, ACC_SUPER</span><br><span class="line">Constant pool:</span><br><span class="line">   #<span class="number">1</span> = Methodref          #<span class="number">5.</span>#<span class="number">24</span>         <span class="comment">// java/lang/Object.&quot;&lt;init&gt;&quot;:()V</span></span><br><span class="line">   #<span class="number">2</span> = Fieldref           #<span class="number">25.</span>#<span class="number">26</span>        <span class="comment">// java/lang/System.out:Ljava/io/PrintStream;</span></span><br><span class="line">   #<span class="number">3</span> = Methodref          #<span class="number">27.</span>#<span class="number">28</span>        <span class="comment">// java/io/PrintStream.println:(I)V</span></span><br><span class="line">   #<span class="number">4</span> = Class              #<span class="number">29</span>            <span class="comment">// com/atguigu/java1/MethodAreaDemo</span></span><br><span class="line">   #<span class="number">5</span> = Class              #<span class="number">30</span>            <span class="comment">// java/lang/Object</span></span><br><span class="line">   #<span class="number">6</span> = Utf8               &lt;init&gt;</span><br><span class="line">   #<span class="number">7</span> = Utf8               ()V</span><br><span class="line">   #<span class="number">8</span> = Utf8               Code</span><br><span class="line">   #<span class="number">9</span> = Utf8               LineNumberTable</span><br><span class="line">  #<span class="number">10</span> = Utf8               LocalVariableTable</span><br><span class="line">  #<span class="number">11</span> = Utf8               <span class="built_in">this</span></span><br><span class="line">  #<span class="number">12</span> = Utf8               Lcom/atguigu/java1/MethodAreaDemo;</span><br><span class="line">  #<span class="number">13</span> = Utf8               main</span><br><span class="line">  #<span class="number">14</span> = Utf8               ([Ljava/lang/String;)V</span><br><span class="line">  #<span class="number">15</span> = Utf8               args</span><br><span class="line">  #<span class="number">16</span> = Utf8               [Ljava/lang/String;</span><br><span class="line">  #<span class="number">17</span> = Utf8               x</span><br><span class="line">  #<span class="number">18</span> = Utf8               I</span><br><span class="line">  #<span class="number">19</span> = Utf8               y</span><br><span class="line">  #<span class="number">20</span> = Utf8               a</span><br><span class="line">  #<span class="number">21</span> = Utf8               b</span><br><span class="line">  #<span class="number">22</span> = Utf8               SourceFile</span><br><span class="line">  #<span class="number">23</span> = Utf8               MethodAreaDemo.java</span><br><span class="line">  #<span class="number">24</span> = NameAndType        #<span class="number">6</span>:#<span class="number">7</span>          <span class="comment">// &quot;&lt;init&gt;&quot;:()V</span></span><br><span class="line">  #<span class="number">25</span> = Class              #<span class="number">31</span>            <span class="comment">// java/lang/System</span></span><br><span class="line">  #<span class="number">26</span> = NameAndType        #<span class="number">32</span>:#<span class="number">33</span>        <span class="comment">// out:Ljava/io/PrintStream;</span></span><br><span class="line">  #<span class="number">27</span> = Class              #<span class="number">34</span>            <span class="comment">// java/io/PrintStream</span></span><br><span class="line">  #<span class="number">28</span> = NameAndType        #<span class="number">35</span>:#<span class="number">36</span>        <span class="comment">// println:(I)V</span></span><br><span class="line">  #<span class="number">29</span> = Utf8               com/atguigu/java1/MethodAreaDemo</span><br><span class="line">  #<span class="number">30</span> = Utf8               java/lang/Object</span><br><span class="line">  #<span class="number">31</span> = Utf8               java/lang/System</span><br><span class="line">  #<span class="number">32</span> = Utf8               out</span><br><span class="line">  #<span class="number">33</span> = Utf8               Ljava/io/PrintStream;</span><br><span class="line">  #<span class="number">34</span> = Utf8               java/io/PrintStream</span><br><span class="line">  #<span class="number">35</span> = Utf8               println</span><br><span class="line">  #<span class="number">36</span> = Utf8               (I)V</span><br><span class="line">&#123;</span><br><span class="line">  <span class="keyword">public</span> com.atguigu.java1.MethodAreaDemo();</span><br><span class="line">    descriptor: ()V</span><br><span class="line">    flags: ACC_PUBLIC</span><br><span class="line">    Code:</span><br><span class="line">      stack=<span class="number">1</span>, locals=<span class="number">1</span>, args_size=<span class="number">1</span></span><br><span class="line">         <span class="number">0</span>: aload_0</span><br><span class="line">         <span class="number">1</span>: invokespecial #<span class="number">1</span>                  <span class="comment">// Method java/lang/Object.&quot;&lt;init&gt;&quot;:()V</span></span><br><span class="line">         <span class="number">4</span>: <span class="keyword">return</span></span><br><span class="line">      LineNumberTable:</span><br><span class="line">        line <span class="number">7</span>: <span class="number">0</span></span><br><span class="line">      LocalVariableTable:</span><br><span class="line">        Start  Length  Slot  Name   Signature</span><br><span class="line">            <span class="number">0</span>       <span class="number">5</span>     <span class="number">0</span>  <span class="built_in">this</span>   Lcom/atguigu/java1/MethodAreaDemo;</span><br><span class="line"></span><br><span class="line">  <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(java.lang.String[])</span>;</span><br><span class="line">    descriptor: ([Ljava/lang/String;)V</span><br><span class="line">    flags: ACC_PUBLIC, ACC_STATIC</span><br><span class="line">    Code:</span><br><span class="line">      stack=<span class="number">3</span>, locals=<span class="number">5</span>, args_size=<span class="number">1</span></span><br><span class="line">         <span class="number">0</span>: sipush        <span class="number">500</span></span><br><span class="line">         <span class="number">3</span>: istore_1</span><br><span class="line">         <span class="number">4</span>: bipush        <span class="number">100</span></span><br><span class="line">         <span class="number">6</span>: istore_2</span><br><span class="line">         <span class="number">7</span>: iload_1</span><br><span class="line">         <span class="number">8</span>: iload_2</span><br><span class="line">         <span class="number">9</span>: idiv</span><br><span class="line">        <span class="number">10</span>: istore_3</span><br><span class="line">        <span class="number">11</span>: bipush        <span class="number">50</span></span><br><span class="line">        <span class="number">13</span>: istore        <span class="number">4</span></span><br><span class="line">        <span class="number">15</span>: getstatic     #<span class="number">2</span>                  <span class="comment">// Field java/lang/System.out:Ljava/io/PrintStream;</span></span><br><span class="line">        <span class="number">18</span>: iload_3</span><br><span class="line">        <span class="number">19</span>: iload         <span class="number">4</span></span><br><span class="line">        <span class="number">21</span>: iadd</span><br><span class="line">        <span class="number">22</span>: invokevirtual #<span class="number">3</span>                  <span class="comment">// Method java/io/PrintStream.println:(I)V</span></span><br><span class="line">        <span class="number">25</span>: <span class="keyword">return</span></span><br><span class="line">      LineNumberTable:</span><br><span class="line">        line <span class="number">9</span>: <span class="number">0</span></span><br><span class="line">        line <span class="number">10</span>: <span class="number">4</span></span><br><span class="line">        line <span class="number">11</span>: <span class="number">7</span></span><br><span class="line">        line <span class="number">12</span>: <span class="number">11</span></span><br><span class="line">        line <span class="number">13</span>: <span class="number">15</span></span><br><span class="line">        line <span class="number">14</span>: <span class="number">25</span></span><br><span class="line">      LocalVariableTable:</span><br><span class="line">        Start  Length  Slot  Name   Signature</span><br><span class="line">            <span class="number">0</span>      <span class="number">26</span>     <span class="number">0</span>  args   [Ljava/lang/String;</span><br><span class="line">            <span class="number">4</span>      <span class="number">22</span>     <span class="number">1</span>     x   I</span><br><span class="line">            <span class="number">7</span>      <span class="number">19</span>     <span class="number">2</span>     y   I</span><br><span class="line">           <span class="number">11</span>      <span class="number">15</span>     <span class="number">3</span>     a   I</span><br><span class="line">           <span class="number">15</span>      <span class="number">11</span>     <span class="number">4</span>     b   I</span><br><span class="line">&#125;</span><br><span class="line">SourceFile: <span class="string">&quot;MethodAreaDemo.java&quot;</span></span><br><span class="line"></span><br></pre></td></tr></table></figure>



<h4 id="图解字节码指令执行流程"><a href="#图解字节码指令执行流程" class="headerlink" title="图解字节码指令执行流程"></a>图解字节码指令执行流程</h4><p>1、初始状态</p>
<img src="https://npm.elemecdn.com/youthlql@1.0.8/JVM/chapter_006/0012.png">

<p>2、首先将操作数500压入操作数栈中</p>
<img src="https://npm.elemecdn.com/youthlql@1.0.8/JVM/chapter_006/0013.png">

<p>3、然后操作数 500 从操作数栈中取出，存储到局部变量表中索引为 1 的位置</p>
<img src="https://npm.elemecdn.com/youthlql@1.0.8/JVM/chapter_006/0014.png">

<p>4、</p>
<img src="https://npm.elemecdn.com/youthlql@1.0.8/JVM/chapter_006/0015.png">

<p>5、</p>
<img src="https://npm.elemecdn.com/youthlql@1.0.8/JVM/chapter_006/0016.png">



<p>6、</p>
<img src="https://npm.elemecdn.com/youthlql@1.0.8/JVM/chapter_006/0017.png">

<p>7、</p>
<img src="https://npm.elemecdn.com/youthlql@1.0.8/JVM/chapter_006/0018.png">

<p>8、</p>
<img src="https://npm.elemecdn.com/youthlql@1.0.8/JVM/chapter_006/0019.png">

<p>9、</p>
<img src="https://npm.elemecdn.com/youthlql@1.0.8/JVM/chapter_006/0020.png">

<p>10、</p>
<img src="https://npm.elemecdn.com/youthlql@1.0.8/JVM/chapter_006/0021.png">

<p>11、图片写错了是#25和#26（获得System类）</p>
<img src="https://npm.elemecdn.com/youthlql@1.0.8/JVM/chapter_006/0022.png">

<p>12、</p>
<img src="https://npm.elemecdn.com/youthlql@1.0.8/JVM/chapter_006/0023.png">

<p>13、</p>
<img src="https://npm.elemecdn.com/youthlql@1.0.8/JVM/chapter_006/0024.png">

<p>15、执行加法运算后，将计算结果放在操作数栈顶</p>
<img src="https://npm.elemecdn.com/youthlql@1.0.8/JVM/chapter_006/0025.png">

<p>16、就是真正的打印</p>
<img src="https://npm.elemecdn.com/youthlql@1.0.8/JVM/chapter_006/0026.png">

<p>17、</p>
<img src="https://npm.elemecdn.com/youthlql@1.0.8/JVM/chapter_006/0027.png">



<p><strong>符号引用 –&gt; 直接饮用</strong></p>
<ol>
<li>上面代码调用 System.out.println() 方法时，首先需要看看 System 类有没有加载，再看看 PrintStream 类有没有加载</li>
<li>如果没有加载，则执行加载，执行时，将常量池中的符号引用（字面量）转换为运行时常量池的直接引用（真正的地址值）</li>
</ol>
<h2 id="方法区演进细节"><a href="#方法区演进细节" class="headerlink" title="方法区演进细节"></a>方法区演进细节</h2><h3 id="永久代演进过程"><a href="#永久代演进过程" class="headerlink" title="永久代演进过程"></a>永久代演进过程</h3><ol>
<li><p>首先明确：只有Hotspot才有永久代。BEA JRockit、IBMJ9等来说，是不存在永久代的概念的。原则上如何实现方法区属于虚拟机实现细节，不受《Java虚拟机规范》管束，并不要求统一</p>
</li>
<li><p>Hotspot中方法区的变化：</p>
</li>
</ol>
<table>
<thead>
<tr>
<th>JDK1.6及以前</th>
<th>有永久代（permanent generation），静态变量存储在永久代上</th>
</tr>
</thead>
<tbody><tr>
<td>JDK1.7</td>
<td>有永久代，但已经逐步 “去永久代”，<strong>字符串常量池，静态变量移除，保存在堆中</strong></td>
</tr>
<tr>
<td>JDK1.8</td>
<td>无永久代，类型信息，字段，方法，常量保存在本地内存的元空间，但字符串常量池、静态变量仍然在堆中。</td>
</tr>
</tbody></table>
<p><strong>JDK6</strong></p>
<p>方法区由永久代实现，使用 JVM 虚拟机内存（虚拟的内存）</p>
<img src="https://npm.elemecdn.com/youthlql@1.0.8/JVM/chapter_006/0028.png">



<p><strong>JDK7</strong></p>
<p>方法区由永久代实现，使用 JVM 虚拟机内存</p>
<img src="https://npm.elemecdn.com/youthlql@1.0.8/JVM/chapter_006/0029.png">



<p><strong>JDK8</strong></p>
<p>方法区由元空间实现，使用物理机本地内存</p>
<img src="https://npm.elemecdn.com/youthlql@1.0.8/JVM/chapter_006/0030.png">





<h3 id="永久代为什么要被元空间替代？"><a href="#永久代为什么要被元空间替代？" class="headerlink" title="永久代为什么要被元空间替代？"></a>永久代为什么要被元空间替代？</h3><blockquote>
<p><strong>官方文档</strong>：<a target="_blank" rel="noopener" href="http://openjdk.java.net/jeps/122">http://openjdk.java.net/jeps/122</a></p>
</blockquote>
<ol>
<li>随着Java8的到来，HotSpot VM中再也见不到永久代了。但是这并不意味着类的元数据信息也消失了。这些数据被移到了一个与堆不相连的本地内存区域，这个区域叫做元空间（Metaspace）。</li>
<li>由于类的元数据分配在本地内存中，元空间的最大可分配空间就是系统可用内存空间。</li>
<li>这项改动是很有必要的，原因有：<ol>
<li>为永久代设置空间大小是很难确定的。在某些场景下，如果动态加载类过多，容易产生Perm区的OOM。比如某个实际Web工程中，因为功能点比较多，在运行过程中，要不断动态加载很多类，经常出现致命错误。<code>Exception in thread &#39;dubbo client x.x connector&#39; java.lang.OutOfMemoryError:PermGen space</code>而元空间和永久代之间最大的区别在于：元空间并不在虚拟机中，而是使用本地内存。 因此，默认情况下，元空间的大小仅受本地内存限制。</li>
<li>对永久代进行调优是很困难的。方法区的垃圾收集主要回收两部分内容：常量池中废弃的常量和不再用的类型，方法区的调优主要是为了降低<strong>Full GC</strong><ol>
<li>有些人认为方法区（如HotSpot虚拟机中的元空间或者永久代）是没有垃圾收集行为的，其实不然。《Java虚拟机规范》对方法区的约束是非常宽松的，提到过可以不要求虚拟机在方法区中实现垃圾收集。事实上也确实有未实现或未能完整实现方法区类型卸载的收集器存在（如JDK11时期的ZGC收集器就不支持类卸载）。</li>
<li>一般来说这个区域的回收效果比较难令人满意，尤其是类型的卸载，条件相当苛刻**。但是这部分区域的回收有时又确实是必要的。以前Sun公司的Bug列表中，曾出现过的若干个严重的Bug就是由于低版本的HotSpot虚拟机对此区域未完全回收而导致内存泄漏。</li>
</ol>
</li>
</ol>
</li>
</ol>
<h3 id="字符串常量池"><a href="#字符串常量池" class="headerlink" title="字符串常量池"></a>字符串常量池</h3><p><strong>字符串常量池 StringTable 为什么要调整位置？</strong></p>
<ul>
<li><p>JDK7中将StringTable放到了堆空间中。因为永久代的回收效率很低，在Full GC的时候才会执行永久代的垃圾回收，而Full GC是老年代的空间不足、永久代不足时才会触发。</p>
</li>
<li><p>这就导致StringTable回收效率不高，而我们开发中会有大量的字符串被创建，回收效率低，导致永久代内存不足。放到堆里，能及时回收内存。</p>
</li>
</ul>
<h3 id="静态变量放在哪里"><a href="#静态变量放在哪里" class="headerlink" title="静态变量放在哪里"></a>静态变量放在哪里</h3><h4 id="对象实体在哪里放着？"><a href="#对象实体在哪里放着？" class="headerlink" title="对象实体在哪里放着？"></a>对象实体在哪里放着？</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 结论：</span></span><br><span class="line"><span class="comment"> * 1、静态引用对应的对象实体(也就是这个new byte[1024 * 1024 * 100])始终都存在堆空间，</span></span><br><span class="line"><span class="comment"> * 2、只是那个变量(相当于下面的arr变量名)在JDK6,JDK7,JDK8存放位置中有所变化</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * jdk7：</span></span><br><span class="line"><span class="comment"> * -Xms200m -Xmx200m -XX:PermSize=300m -XX:MaxPermSize=300m -XX:+PrintGCDetails</span></span><br><span class="line"><span class="comment"> * jdk 8：</span></span><br><span class="line"><span class="comment"> * -Xms200m -Xmx200m -XX:MetaspaceSize=300m -XX:MaxMetaspaceSize=300m -XX:+PrintGCDetails</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">StaticFieldTest</span> &#123;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> <span class="type">byte</span>[] arr = <span class="keyword">new</span> <span class="title class_">byte</span>[<span class="number">1024</span> * <span class="number">1024</span> * <span class="number">100</span>];<span class="comment">//100MB</span></span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">        System.out.println(StaticFieldTest.arr);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<p>JDK6环境下</p>
<img src="https://npm.elemecdn.com/youthlql@1.0.8/JVM/chapter_006/0031.png" alt="image-20201113224231761" />

<p>JDK7环境下</p>
<img src="https://npm.elemecdn.com/youthlql@1.0.8/JVM/chapter_006/0032.png">

<p>JDK8环境</p>
<img src="https://npm.elemecdn.com/youthlql@1.0.8/JVM/chapter_006/0033.png">



<h4 id="变量-名-存放在哪里？"><a href="#变量-名-存放在哪里？" class="headerlink" title="变量(名)存放在哪里？"></a>变量(名)存放在哪里？</h4><p>这个问题需要用JHSDB工具来进行分析，这个工具是JDK9开始自带的(JDK9以前没有)，在bin目录下可以找到</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.atguigu.java1;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 《深入理解Java虚拟机》中的案例：</span></span><br><span class="line"><span class="comment"> * staticObj、instanceObj、localObj存放在哪里？</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">StaticObjTest</span> &#123;</span><br><span class="line">    <span class="keyword">static</span> <span class="keyword">class</span> <span class="title class_">Test</span> &#123;</span><br><span class="line">        <span class="keyword">static</span> <span class="type">ObjectHolder</span> <span class="variable">staticObj</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">ObjectHolder</span>();</span><br><span class="line">        <span class="type">ObjectHolder</span> <span class="variable">instanceObj</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">ObjectHolder</span>();</span><br><span class="line"></span><br><span class="line">        <span class="keyword">void</span> <span class="title function_">foo</span><span class="params">()</span> &#123;</span><br><span class="line">            <span class="type">ObjectHolder</span> <span class="variable">localObj</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">ObjectHolder</span>();</span><br><span class="line">            System.out.println(<span class="string">&quot;done&quot;</span>);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">class</span> <span class="title class_">ObjectHolder</span> &#123;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">        <span class="type">Test</span> <span class="variable">test</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">StaticObjTest</span>.Test();</span><br><span class="line">        test.foo();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<p><strong>JDK6环境下</strong></p>
<p>1、staticObj随着Test的类型信息存放在方法区</p>
<p>2、instanceObj随着Test的对象实例存放在Java堆</p>
<p>3、localObject则是存放在foo()方法栈帧的局部变量表中。</p>
<p>4、测试发现：三个对象的数据在内存中的地址都落在Eden区范围内，所以结论：<strong>只要是对象实例必然会在Java堆中分配</strong>。</p>
<img src="https://npm.elemecdn.com/youthlql@1.0.8/JVM/chapter_006/0034.png">

<blockquote>
<p>1、0x00007f32c7800000(Eden区的起始地址)    —-   0x00007f32c7b50000(Eden区的终止地址)  </p>
<p>2、可以发现三个变量都在这个范围内</p>
<p>3、所以可以得到上面结论</p>
</blockquote>
<p>5、接着，找到了一个引用该staticObj对象的地方，是在一个java.lang.Class的实例里，并且给出了这个实例的地址，通过Inspector查看该对象实例，可以清楚看到这确实是一个java.lang.Class类型的对象实例，里面有一个名为staticobj的实例字段：</p>
<img src="https://npm.elemecdn.com/youthlql@1.0.8/JVM/chapter_006/0035.png">

<p>从《Java虚拟机规范》所定义的概念模型来看，所有Class相关的信息都应该存放在方法区之中，但方法区该如何实现，《Java虚拟机规范》并未做出规定，这就成了一件允许不同虚拟机自己灵活把握的事情。JDK7及其以后版本的HotSpot虚拟机选择把静态变量与类型在Java语言一端的映射Class对象存放在一起，<strong>存储于Java堆之中</strong>，从我们的实验中也明确验证了这一点</p>
<h2 id="方法区的垃圾回收"><a href="#方法区的垃圾回收" class="headerlink" title="方法区的垃圾回收"></a>方法区的垃圾回收</h2><ol>
<li><p>有些人认为方法区（如Hotspot虚拟机中的元空间或者永久代）是没有垃圾收集行为的，其实不然。《Java虚拟机规范》对方法区的约束是非常宽松的，提到过可以不要求虚拟机在方法区中实现垃圾收集。事实上也确实有未实现或未能完整实现方法区<strong>类型卸载</strong>的收集器存在（如JDK11时期的ZGC收集器就不支持类卸载）。</p>
</li>
<li><p>一般来说这个区域的回收效果比较难令人满意，尤其是类型的卸载，条件相当苛刻。但是这部分区域的回收有时又确实是必要的。以前sun公司的Bug列表中，曾出现过的若干个严重的Bug就是由于低版本的HotSpot虚拟机对此区域未完全回收而导致内存泄漏。</p>
</li>
<li><p>方法区的垃圾收集主要回收两部分内容：<strong>常量池中废弃的常量和不再使用的类型</strong>。</p>
</li>
<li><p>先来说说方法区内常量池之中主要存放的两大类常量：字面量和符号引用。字面量比较接近Java语言层次的常量概念，如文本字符串、被声明为final的常量值等。而符号引用则属于编译原理方面的概念，包括下面三类常量：</p>
<ul>
<li>类和接口的全限定名</li>
<li>字段的名称和描述符</li>
<li>方法的名称和描述符</li>
</ul>
</li>
<li><p>HotSpot虚拟机对常量池的回收策略是很明确的，只要常量池中的常量没有被任何地方引用，就可以被回收。</p>
</li>
<li><p>回收废弃常量与回收Java堆中的对象非常类似。（关于常量的回收比较简单，重点是类的回收）</p>
</li>
</ol>
<p>下面也称作<strong>类卸载</strong></p>
<p>1、判定一个常量是否“废弃”还是相对简单，而要判定一个类型是否属于“不再被使用的类”的条件就比较苛刻了。需要同时满足下面三个条件：</p>
<ul>
<li><p>该类所有的实例都已经被回收，也就是Java堆中不存在该类及其任何派生子类的实例。</p>
</li>
<li><p>加载该类的类加载器已经被回收，这个条件除非是经过精心设计的可替换类加载器的场景，如OSGi、JSP的重加载等，否则通常是很难达成的。</p>
</li>
<li><p>该类对应的java.lang.Class对象没有在任何地方被引用，无法在任何地方通过反射访问该类的方法。</p>
</li>
</ul>
<p>2、Java虚拟机被允许对满足上述三个条件的无用类进行回收，这里说的仅仅是“被允许”，而并不是和对象一样，没有引用了就必然会回收。关于是否要对类型进行回收，HotSpot虚拟机提供了<code>-Xnoclassgc</code>参数进行控制，还可以使用<code>-verbose:class</code> 以及 <code>-XX：+TraceClass-Loading</code>、<code>-XX：+TraceClassUnLoading</code>查看类加载和卸载信息</p>
<p>3、在大量使用反射、动态代理、CGLib等字节码框架，动态生成JSP以及OSGi这类频繁自定义类加载器的场景中，通常都需要Java虚拟机具备类型卸载的能力，以保证不会对方法区造成过大的内存压力。</p>
<h2 id="运行时数据区总结"><a href="#运行时数据区总结" class="headerlink" title="运行时数据区总结"></a>运行时数据区总结</h2><img src="https://npm.elemecdn.com/youthlql@1.0.8/JVM/chapter_006/0036.png">



<h2 id="直接内存"><a href="#直接内存" class="headerlink" title="直接内存"></a>直接内存</h2><h3 id="直接内存概述"><a href="#直接内存概述" class="headerlink" title="直接内存概述"></a>直接内存概述</h3><ol>
<li><p>不是虚拟机运行时数据区的一部分，也不是《Java虚拟机规范》中定义的内存区域。</p>
</li>
<li><p>直接内存是在Java堆外的、直接向系统申请的内存区间。</p>
</li>
<li><p>来源于NIO，通过存在堆中的DirectByteBuffer操作Native内存</p>
</li>
<li><p>通常，访问直接内存的速度会优于Java堆。即读写性能高。</p>
</li>
<li><p>因此出于性能考虑，读写频繁的场合可能会考虑使用直接内存。</p>
</li>
<li><p>Java的NIO库允许Java程序使用直接内存，用于数据缓冲区</p>
</li>
</ol>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> *  IO                  NIO (New IO / Non-Blocking IO)</span></span><br><span class="line"><span class="comment"> *  byte[] / char[]     Buffer</span></span><br><span class="line"><span class="comment"> *  Stream              Channel</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * 查看直接内存的占用与释放</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">BufferTest</span> &#123;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="type">int</span> <span class="variable">BUFFER</span> <span class="operator">=</span> <span class="number">1024</span> * <span class="number">1024</span> * <span class="number">1024</span>;<span class="comment">//1GB</span></span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span>&#123;</span><br><span class="line">        <span class="comment">//直接分配本地内存空间</span></span><br><span class="line">        <span class="type">ByteBuffer</span> <span class="variable">byteBuffer</span> <span class="operator">=</span> ByteBuffer.allocateDirect(BUFFER);</span><br><span class="line">        System.out.println(<span class="string">&quot;直接内存分配完毕，请求指示！&quot;</span>);</span><br><span class="line"></span><br><span class="line">        <span class="type">Scanner</span> <span class="variable">scanner</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Scanner</span>(System.in);</span><br><span class="line">        scanner.next();</span><br><span class="line"></span><br><span class="line">        System.out.println(<span class="string">&quot;直接内存开始释放！&quot;</span>);</span><br><span class="line">        byteBuffer = <span class="literal">null</span>;</span><br><span class="line">        System.gc();</span><br><span class="line">        scanner.next();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<p>直接占用了 1G 的本地内存</p>
<img src="https://npm.elemecdn.com/youthlql@1.0.8/JVM/chapter_006/0037.jpg">



<h3 id="BIO-与-NIO"><a href="#BIO-与-NIO" class="headerlink" title="BIO 与 NIO"></a>BIO 与 NIO</h3><p><strong>非直接缓存区（BIO）</strong></p>
<p>原来采用BIO的架构，在读写本地文件时，我们需要从用户态切换成内核态</p>
<img src="https://npm.elemecdn.com/youthlql@1.0.8/JVM/chapter_006/0038.png">

<p><strong>直接缓冲区（NIO）</strong></p>
<p>NIO 直接操作物理磁盘，省去了中间过程</p>
<img src="https://npm.elemecdn.com/youthlql@1.0.8/JVM/chapter_006/0039.png">

<h3 id="直接内存与-OOM"><a href="#直接内存与-OOM" class="headerlink" title="直接内存与 OOM"></a>直接内存与 OOM</h3><ol>
<li><p>直接内存也可能导致OutofMemoryError异常</p>
</li>
<li><p>由于直接内存在Java堆外，因此它的大小不会直接受限于-Xmx指定的最大堆大小，但是系统内存是有限的，Java堆和直接内存的总和依然受限于操作系统能给出的最大内存。</p>
</li>
<li><p>直接内存的缺点为：</p>
<ul>
<li>分配回收成本较高</li>
<li>不受JVM内存回收管理</li>
</ul>
</li>
<li><p>直接内存大小可以通过MaxDirectMemorySize设置</p>
</li>
<li><p>如果不指定，默认与堆的最大值-Xmx参数值一致</p>
</li>
</ol>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line">/**</span><br><span class="line"> * 本地内存的OOM:  OutOfMemoryError: Direct buffer memory</span><br><span class="line"> *</span><br><span class="line"> */</span><br><span class="line">public class BufferTest2 &#123;</span><br><span class="line">    private static final int BUFFER = 1024 * 1024 * 20;//20MB</span><br><span class="line"></span><br><span class="line">    public static void main(String[] args) &#123;</span><br><span class="line">        ArrayList&lt;ByteBuffer&gt; list = new ArrayList&lt;&gt;();</span><br><span class="line"></span><br><span class="line">        int count = 0;</span><br><span class="line">        try &#123;</span><br><span class="line">            while(true)&#123;</span><br><span class="line">                ByteBuffer byteBuffer = ByteBuffer.allocateDirect(BUFFER);</span><br><span class="line">                list.add(byteBuffer);</span><br><span class="line">                count++;</span><br><span class="line">                try &#123;</span><br><span class="line">                    Thread.sleep(100);</span><br><span class="line">                &#125; catch (InterruptedException e) &#123;</span><br><span class="line">                    e.printStackTrace();</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125; finally &#123;</span><br><span class="line">            System.out.println(count);</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure>



<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">Exception in thread <span class="string">&quot;main&quot;</span> java.lang.OutOfMemoryError: Direct buffer memory</span><br><span class="line">	at java.nio.Bits.reserveMemory(Bits.java:<span class="number">694</span>)</span><br><span class="line">	at java.nio.DirectByteBuffer.&lt;init&gt;(DirectByteBuffer.java:<span class="number">123</span>)</span><br><span class="line">	at java.nio.ByteBuffer.allocateDirect(ByteBuffer.java:<span class="number">311</span>)</span><br><span class="line">	at com.atguigu.java.BufferTest2.main(BufferTest2.java:<span class="number">21</span>)</span><br></pre></td></tr></table></figure>





<img src="https://npm.elemecdn.com/youthlql@1.0.8/JVM/chapter_006/0040.jpg">





<h2 id="常见面试题"><a href="#常见面试题" class="headerlink" title="常见面试题"></a>常见面试题</h2><ol>
<li>百度<ul>
<li>三面：说一下JVM内存模型吧，有哪些区？分别干什么的？</li>
</ul>
</li>
<li>蚂蚁金服：<ul>
<li>Java8的内存分代改进</li>
<li>JVM内存分哪几个区，每个区的作用是什么？</li>
<li>一面：JVM内存分布&#x2F;内存结构？栈和堆的区别？堆的结构？为什么两个survivor区？</li>
<li>二面：Eden和survior的比例分配</li>
</ul>
</li>
<li>小米：<ul>
<li>jvm内存分区，为什么要有新生代和老年代</li>
</ul>
</li>
<li>字节跳动：<ul>
<li>二面：Java的内存分区</li>
<li>二面：讲讲vm运行时数据库区</li>
<li>什么时候对象会进入老年代？</li>
</ul>
</li>
<li>京东：<ul>
<li>JVM的内存结构，Eden和Survivor比例。</li>
<li>JVM内存为什么要分成新生代，老年代，持久代。新生代中为什么要分为Eden和survivor。</li>
</ul>
</li>
<li>天猫：<ul>
<li>一面：Jvm内存模型以及分区，需要详细到每个区放什么。</li>
<li>一面：JVM的内存模型，Java8做了什么改</li>
</ul>
</li>
<li>拼多多：<ul>
<li>JVM内存分哪几个区，每个区的作用是什么？</li>
</ul>
</li>
<li>美团：<ul>
<li>java内存分配</li>
<li>jvm的永久代中会发生垃圾回收吗？</li>
<li>一面：jvm内存分区，为什么要有新生代和老年代？</li>
</ul>
</li>
</ol>
</article><div class="post-copyright"><div class="post-copyright__author"><span class="post-copyright-meta">文章作者: </span><span class="post-copyright-info"><a href="http://example.com">Alix</a></span></div><div class="post-copyright__type"><span class="post-copyright-meta">文章链接: </span><span class="post-copyright-info"><a href="http://example.com/2021/11/13/JVM/JVM%E7%B3%BB%E5%88%97-%E7%AC%AC6%E7%AB%A0-%E6%96%B9%E6%B3%95%E5%8C%BA/">http://example.com/2021/11/13/JVM/JVM%E7%B3%BB%E5%88%97-%E7%AC%AC6%E7%AB%A0-%E6%96%B9%E6%B3%95%E5%8C%BA/</a></span></div><div class="post-copyright__notice"><span class="post-copyright-meta">版权声明: </span><span class="post-copyright-info">本博客所有文章除特别声明外，均采用 <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/" target="_blank">CC BY-NC-SA 4.0</a> 许可协议。转载请注明来自 <a href="http://example.com" target="_blank">石银的小酒屋</a>！</span></div></div><div class="tag_share"><div class="post-meta__tag-list"><a class="post-meta__tags" href="/tags/JVM/">JVM</a><a class="post-meta__tags" href="/tags/%E8%99%9A%E6%8B%9F%E6%9C%BA/">虚拟机</a></div><div class="post_share"><div class="social-share" data-image="https://npm.elemecdn.com/lql_static@latest/logo/jvm.png" data-sites="facebook,twitter,wechat,weibo,qq"></div><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/butterfly-extsrc/sharejs/dist/css/share.min.css" media="print" onload="this.media='all'"><script src="https://cdn.jsdelivr.net/npm/butterfly-extsrc/sharejs/dist/js/social-share.min.js" defer></script></div></div><nav class="pagination-post" id="pagination"><div class="prev-post pull-left"><a href="/2021/11/14/JVM/JVM%E7%B3%BB%E5%88%97-%E7%AC%AC7%E7%AB%A0-%E5%AF%B9%E8%B1%A1%E7%9A%84%E5%AE%9E%E4%BE%8B%E5%8C%96%E5%86%85%E5%AD%98%E5%B8%83%E5%B1%80%E4%B8%8E%E8%AE%BF%E9%97%AE%E5%AE%9A%E4%BD%8D/"><img class="prev-cover" src="https://npm.elemecdn.com/lql_static@latest/logo/jvm.png" onerror="onerror=null;src='/img/404.jpg'" alt="cover of previous post"><div class="pagination-info"><div class="label">上一篇</div><div class="prev_info">JVM系列-第7章-对象的实例化内存布局与访问定位</div></div></a></div><div class="next-post pull-right"><a href="/2021/11/11/JVM/JVM%E7%B3%BB%E5%88%97-%E7%AC%AC5%E7%AB%A0-%E5%A0%86/"><img class="next-cover" src="https://npm.elemecdn.com/lql_static@latest/logo/jvm.png" onerror="onerror=null;src='/img/404.jpg'" alt="cover of next post"><div class="pagination-info"><div class="label">下一篇</div><div class="next_info">JVM系列-第5章-堆</div></div></a></div></nav><div class="relatedPosts"><div class="headline"><i class="fas fa-thumbs-up fa-fw"></i><span>相关推荐</span></div><div class="relatedPosts-list"><div><a href="/2021/11/17/JVM/JVM%E7%B3%BB%E5%88%97-%E7%AC%AC11%E7%AB%A0-%E5%9E%83%E5%9C%BE%E5%9B%9E%E6%94%B6%E7%9B%B8%E5%85%B3%E6%A6%82%E5%BF%B5/" title="JVM系列-第11章-垃圾回收相关概念"><img class="cover" src="https://npm.elemecdn.com/lql_static@latest/logo/jvm.png" alt="cover"><div class="content is-center"><div class="date"><i class="far fa-calendar-alt fa-fw"></i> 2021-11-17</div><div class="title">JVM系列-第11章-垃圾回收相关概念</div></div></a></div><div><a href="/2021/11/16/JVM/JVM%E7%B3%BB%E5%88%97-%E7%AC%AC10%E7%AB%A0-%E5%9E%83%E5%9C%BE%E5%9B%9E%E6%94%B6%E6%A6%82%E8%BF%B0%E5%92%8C%E7%9B%B8%E5%85%B3%E7%AE%97%E6%B3%95/" title="JVM系列-第10章-垃圾回收概述和相关算法"><img class="cover" src="https://npm.elemecdn.com/lql_static@latest/logo/jvm.png" alt="cover"><div class="content is-center"><div class="date"><i class="far fa-calendar-alt fa-fw"></i> 2021-11-16</div><div class="title">JVM系列-第10章-垃圾回收概述和相关算法</div></div></a></div><div><a href="/2021/11/19/JVM/JVM%E7%B3%BB%E5%88%97-%E7%AC%AC12%E7%AB%A0-%E5%9E%83%E5%9C%BE%E5%9B%9E%E6%94%B6%E5%99%A8/" title="JVM系列-第12章-垃圾回收器"><img class="cover" src="https://npm.elemecdn.com/lql_static@latest/logo/jvm.png" alt="cover"><div class="content is-center"><div class="date"><i class="far fa-calendar-alt fa-fw"></i> 2021-11-19</div><div class="title">JVM系列-第12章-垃圾回收器</div></div></a></div><div><a href="/2021/11/09/JVM/JVM%E7%B3%BB%E5%88%97-%E7%AC%AC3%E7%AB%A0-%E8%BF%90%E8%A1%8C%E6%97%B6%E6%95%B0%E6%8D%AE%E5%8C%BA/" title="JVM系列-第3章-运行时数据区"><img class="cover" src="https://npm.elemecdn.com/lql_static@latest/logo/jvm.png" alt="cover"><div class="content is-center"><div class="date"><i class="far fa-calendar-alt fa-fw"></i> 2021-11-09</div><div class="title">JVM系列-第3章-运行时数据区</div></div></a></div><div><a href="/2021/11/02/JVM/JVM%E7%B3%BB%E5%88%97-%E7%AC%AC1%E7%AB%A0-JVM%E4%B8%8EJava%E4%BD%93%E7%B3%BB%E7%BB%93%E6%9E%84/" title="JVM系列-第1章-JVM与Java体系结构"><img class="cover" src="https://npm.elemecdn.com/lql_static@latest/logo/jvm.png" alt="cover"><div class="content is-center"><div class="date"><i class="far fa-calendar-alt fa-fw"></i> 2021-11-02</div><div class="title">JVM系列-第1章-JVM与Java体系结构</div></div></a></div><div><a href="/2021/11/02/JVM/JVM%E7%B3%BB%E5%88%97-%E7%AC%AC2%E7%AB%A0-%E7%B1%BB%E5%8A%A0%E8%BD%BD%E5%AD%90%E7%B3%BB%E7%BB%9F/" title="JVM系列-第2章-类加载子系统"><img class="cover" src="https://npm.elemecdn.com/lql_static@latest/logo/jvm.png" alt="cover"><div class="content is-center"><div class="date"><i class="far fa-calendar-alt fa-fw"></i> 2021-11-02</div><div class="title">JVM系列-第2章-类加载子系统</div></div></a></div></div></div><hr/><div id="post-comment"><div class="comment-head"><div class="comment-headline"><i class="fas fa-comments fa-fw"></i><span> 评论</span></div><div id="comment-switch"><span class="first-comment">Valine</span><span class="switch-btn"></span><span class="second-comment">Disqus</span></div></div><div class="comment-wrap"><div><div class="vcomment" id="vcomment"></div></div><div><div id="disqus_thread"></div></div></div></div></div><div class="aside-content" id="aside-content"><div class="card-widget card-info"><div class="is-center"><div class="avatar-img"><img src="/assetse/%E5%A4%B4%E5%83%8F.jpg" onerror="this.onerror=null;this.src='/img/friend_404.gif'" alt="avatar"/></div><div class="author-info__name">Alix</div><div class="author-info__description">归途也还可爱</div></div><div class="card-info-data site-data is-center"><a href="/archives/"><div class="headline">文章</div><div class="length-num">23</div></a><a href="/tags/"><div class="headline">标签</div><div class="length-num">9</div></a><a href="/categories/"><div class="headline">分类</div><div class="length-num">7</div></a></div><a id="card-info-btn" target="_blank" rel="noopener" href="https://github.com/923584731"><i class="fab fa-github"></i><span>Follow Me</span></a><div class="card-info-social-icons is-center"><a class="social-icon" href="https://github.com/923584731" target="_blank" title="Github"><i class="fab fa-github"></i></a><a class="social-icon" href="mailto:923584731@qq.com" target="_blank" title="Email"><i class="fas fa-envelope"></i></a><a class="social-icon" href="/atom.xml" target="_blank" title="Rss"><i class="fas fa-rss"></i></a></div></div><div class="card-widget card-announcement"><div class="item-headline"><i class="fas fa-bullhorn fa-shake"></i><span>公告</span></div><div class="announcement_content">少年郎的博客网站</div></div><div class="sticky_layout"><div class="card-widget" id="card-toc"><div class="item-headline"><i class="fas fa-stream"></i><span>目录</span><span class="toc-percentage"></span></div><div class="toc-content"><ol class="toc"><li class="toc-item toc-level-1"><a class="toc-link" href="#%E6%96%B9%E6%B3%95%E5%8C%BA"><span class="toc-number">1.</span> <span class="toc-text">方法区</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#%E6%A0%88%E3%80%81%E5%A0%86%E3%80%81%E6%96%B9%E6%B3%95%E5%8C%BA%E7%9A%84%E4%BA%A4%E4%BA%92%E5%85%B3%E7%B3%BB"><span class="toc-number">1.1.</span> <span class="toc-text">栈、堆、方法区的交互关系</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E6%96%B9%E6%B3%95%E5%8C%BA%E7%9A%84%E7%90%86%E8%A7%A3"><span class="toc-number">1.2.</span> <span class="toc-text">方法区的理解</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#%E6%96%B9%E6%B3%95%E5%8C%BA%E5%9C%A8%E5%93%AA%E9%87%8C%EF%BC%9F"><span class="toc-number">1.2.1.</span> <span class="toc-text">方法区在哪里？</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E6%96%B9%E6%B3%95%E5%8C%BA%E7%9A%84%E5%9F%BA%E6%9C%AC%E7%90%86%E8%A7%A3"><span class="toc-number">1.2.2.</span> <span class="toc-text">方法区的基本理解</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#HotSpot%E6%96%B9%E6%B3%95%E5%8C%BA%E6%BC%94%E8%BF%9B"><span class="toc-number">1.2.3.</span> <span class="toc-text">HotSpot方法区演进</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E8%AE%BE%E7%BD%AE%E6%96%B9%E6%B3%95%E5%8C%BA%E5%A4%A7%E5%B0%8F%E4%B8%8E-OOM"><span class="toc-number">1.3.</span> <span class="toc-text">设置方法区大小与 OOM</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#JDK7%E5%8F%8A%E4%BB%A5%E5%89%8D-%E6%B0%B8%E4%B9%85%E4%BB%A3"><span class="toc-number">1.3.1.</span> <span class="toc-text">JDK7及以前(永久代)</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#JDK8%E5%8F%8A%E4%BB%A5%E5%90%8E-%E5%85%83%E7%A9%BA%E9%97%B4"><span class="toc-number">1.3.2.</span> <span class="toc-text">JDK8及以后(元空间)</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E6%96%B9%E6%B3%95%E5%8C%BAOOM"><span class="toc-number">1.3.3.</span> <span class="toc-text">方法区OOM</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%A6%82%E4%BD%95%E8%A7%A3%E5%86%B3OOM"><span class="toc-number">1.3.4.</span> <span class="toc-text">如何解决OOM</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E6%96%B9%E6%B3%95%E5%8C%BA%E7%9A%84%E5%86%85%E9%83%A8%E7%BB%93%E6%9E%84"><span class="toc-number">1.4.</span> <span class="toc-text">方法区的内部结构</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#%E6%96%B9%E6%B3%95%E5%8C%BA%E5%AD%98%E5%82%A8%E4%BB%80%E4%B9%88%EF%BC%9F"><span class="toc-number">1.4.1.</span> <span class="toc-text">方法区存储什么？</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#%E6%A6%82%E5%BF%B5"><span class="toc-number">1.4.1.1.</span> <span class="toc-text">概念</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E4%B8%BE%E4%BE%8B"><span class="toc-number">1.4.1.2.</span> <span class="toc-text">举例</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#non-final-%E7%B1%BB%E5%9E%8B%E7%9A%84%E7%B1%BB%E5%8F%98%E9%87%8F"><span class="toc-number">1.4.2.</span> <span class="toc-text">non-final 类型的类变量</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#%E5%85%A8%E5%B1%80%E5%B8%B8%E9%87%8F%EF%BC%9Astatic-final"><span class="toc-number">1.4.2.1.</span> <span class="toc-text">全局常量：static final</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E8%BF%90%E8%A1%8C%E6%97%B6%E5%B8%B8%E9%87%8F%E6%B1%A0"><span class="toc-number">1.4.3.</span> <span class="toc-text">运行时常量池</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#%E8%BF%90%E8%A1%8C%E6%97%B6%E5%B8%B8%E9%87%8F%E6%B1%A0-VS-%E5%B8%B8%E9%87%8F%E6%B1%A0"><span class="toc-number">1.4.3.1.</span> <span class="toc-text">运行时常量池 VS 常量池</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E5%B8%B8%E9%87%8F%E6%B1%A0"><span class="toc-number">1.4.3.2.</span> <span class="toc-text">常量池</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E8%BF%90%E8%A1%8C%E6%97%B6%E5%B8%B8%E9%87%8F%E6%B1%A0-1"><span class="toc-number">1.4.3.3.</span> <span class="toc-text">运行时常量池</span></a></li></ol></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E6%96%B9%E6%B3%95%E5%8C%BA%E7%9A%84%E4%BD%BF%E7%94%A8%E4%B8%BE%E4%BE%8B"><span class="toc-number">1.5.</span> <span class="toc-text">方法区的使用举例</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#%E5%9B%BE%E8%A7%A3%E5%AD%97%E8%8A%82%E7%A0%81%E6%8C%87%E4%BB%A4%E6%89%A7%E8%A1%8C%E6%B5%81%E7%A8%8B"><span class="toc-number">1.5.0.1.</span> <span class="toc-text">图解字节码指令执行流程</span></a></li></ol></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E6%96%B9%E6%B3%95%E5%8C%BA%E6%BC%94%E8%BF%9B%E7%BB%86%E8%8A%82"><span class="toc-number">1.6.</span> <span class="toc-text">方法区演进细节</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#%E6%B0%B8%E4%B9%85%E4%BB%A3%E6%BC%94%E8%BF%9B%E8%BF%87%E7%A8%8B"><span class="toc-number">1.6.1.</span> <span class="toc-text">永久代演进过程</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E6%B0%B8%E4%B9%85%E4%BB%A3%E4%B8%BA%E4%BB%80%E4%B9%88%E8%A6%81%E8%A2%AB%E5%85%83%E7%A9%BA%E9%97%B4%E6%9B%BF%E4%BB%A3%EF%BC%9F"><span class="toc-number">1.6.2.</span> <span class="toc-text">永久代为什么要被元空间替代？</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%AD%97%E7%AC%A6%E4%B8%B2%E5%B8%B8%E9%87%8F%E6%B1%A0"><span class="toc-number">1.6.3.</span> <span class="toc-text">字符串常量池</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E9%9D%99%E6%80%81%E5%8F%98%E9%87%8F%E6%94%BE%E5%9C%A8%E5%93%AA%E9%87%8C"><span class="toc-number">1.6.4.</span> <span class="toc-text">静态变量放在哪里</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#%E5%AF%B9%E8%B1%A1%E5%AE%9E%E4%BD%93%E5%9C%A8%E5%93%AA%E9%87%8C%E6%94%BE%E7%9D%80%EF%BC%9F"><span class="toc-number">1.6.4.1.</span> <span class="toc-text">对象实体在哪里放着？</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E5%8F%98%E9%87%8F-%E5%90%8D-%E5%AD%98%E6%94%BE%E5%9C%A8%E5%93%AA%E9%87%8C%EF%BC%9F"><span class="toc-number">1.6.4.2.</span> <span class="toc-text">变量(名)存放在哪里？</span></a></li></ol></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E6%96%B9%E6%B3%95%E5%8C%BA%E7%9A%84%E5%9E%83%E5%9C%BE%E5%9B%9E%E6%94%B6"><span class="toc-number">1.7.</span> <span class="toc-text">方法区的垃圾回收</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E8%BF%90%E8%A1%8C%E6%97%B6%E6%95%B0%E6%8D%AE%E5%8C%BA%E6%80%BB%E7%BB%93"><span class="toc-number">1.8.</span> <span class="toc-text">运行时数据区总结</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E7%9B%B4%E6%8E%A5%E5%86%85%E5%AD%98"><span class="toc-number">1.9.</span> <span class="toc-text">直接内存</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#%E7%9B%B4%E6%8E%A5%E5%86%85%E5%AD%98%E6%A6%82%E8%BF%B0"><span class="toc-number">1.9.1.</span> <span class="toc-text">直接内存概述</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#BIO-%E4%B8%8E-NIO"><span class="toc-number">1.9.2.</span> <span class="toc-text">BIO 与 NIO</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E7%9B%B4%E6%8E%A5%E5%86%85%E5%AD%98%E4%B8%8E-OOM"><span class="toc-number">1.9.3.</span> <span class="toc-text">直接内存与 OOM</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E5%B8%B8%E8%A7%81%E9%9D%A2%E8%AF%95%E9%A2%98"><span class="toc-number">1.10.</span> <span class="toc-text">常见面试题</span></a></li></ol></li></ol></div></div><div class="card-widget card-recent-post"><div class="item-headline"><i class="fas fa-history"></i><span>最新文章</span></div><div class="aside-list"><div class="aside-list-item"><a class="thumbnail" href="/2023/04/20/%E9%94%81%E6%9C%BA%E5%88%B6/" title="数据库并发锁机制"><img src="/assetse/y13.jpg" onerror="this.onerror=null;this.src='/img/404.jpg'" alt="数据库并发锁机制"/></a><div class="content"><a class="title" href="/2023/04/20/%E9%94%81%E6%9C%BA%E5%88%B6/" title="数据库并发锁机制">数据库并发锁机制</a><time datetime="2023-04-20T06:55:04.000Z" title="发表于 2023-04-20 14:55:04">2023-04-20</time></div></div><div class="aside-list-item"><a class="thumbnail" href="/2022/04/21/netty/Netty%E5%85%A5%E9%97%A8-%E7%AC%AC%E4%B8%89%E8%AF%9D/" title="Netty入门-第三话"><img src="https://npm.elemecdn.com/lql_static@latest/logo/netty_logo.jpg" onerror="this.onerror=null;this.src='/img/404.jpg'" alt="Netty入门-第三话"/></a><div class="content"><a class="title" href="/2022/04/21/netty/Netty%E5%85%A5%E9%97%A8-%E7%AC%AC%E4%B8%89%E8%AF%9D/" title="Netty入门-第三话">Netty入门-第三话</a><time datetime="2022-04-21T09:38:58.000Z" title="发表于 2022-04-21 17:38:58">2022-04-21</time></div></div><div class="aside-list-item"><a class="thumbnail" href="/2022/04/15/netty/Netty%E5%85%A5%E9%97%A8-%E7%AC%AC%E4%BA%8C%E8%AF%9D/" title="Netty入门-第二话"><img src="https://npm.elemecdn.com/lql_static@latest/logo/netty_logo.jpg" onerror="this.onerror=null;this.src='/img/404.jpg'" alt="Netty入门-第二话"/></a><div class="content"><a class="title" href="/2022/04/15/netty/Netty%E5%85%A5%E9%97%A8-%E7%AC%AC%E4%BA%8C%E8%AF%9D/" title="Netty入门-第二话">Netty入门-第二话</a><time datetime="2022-04-15T06:21:58.000Z" title="发表于 2022-04-15 14:21:58">2022-04-15</time></div></div><div class="aside-list-item"><a class="thumbnail" href="/2022/04/08/netty/Netty%E5%85%A5%E9%97%A8-%E7%AC%AC%E4%B8%80%E8%AF%9D/" title="Netty入门-第一话"><img src="https://npm.elemecdn.com/lql_static@latest/logo/netty_logo.jpg" onerror="this.onerror=null;this.src='/img/404.jpg'" alt="Netty入门-第一话"/></a><div class="content"><a class="title" href="/2022/04/08/netty/Netty%E5%85%A5%E9%97%A8-%E7%AC%AC%E4%B8%80%E8%AF%9D/" title="Netty入门-第一话">Netty入门-第一话</a><time datetime="2022-04-08T06:21:58.000Z" title="发表于 2022-04-08 14:21:58">2022-04-08</time></div></div><div class="aside-list-item"><a class="thumbnail" href="/2021/11/19/JVM/JVM%E7%B3%BB%E5%88%97-%E7%AC%AC12%E7%AB%A0-%E5%9E%83%E5%9C%BE%E5%9B%9E%E6%94%B6%E5%99%A8/" title="JVM系列-第12章-垃圾回收器"><img src="https://npm.elemecdn.com/lql_static@latest/logo/jvm.png" onerror="this.onerror=null;this.src='/img/404.jpg'" alt="JVM系列-第12章-垃圾回收器"/></a><div class="content"><a class="title" href="/2021/11/19/JVM/JVM%E7%B3%BB%E5%88%97-%E7%AC%AC12%E7%AB%A0-%E5%9E%83%E5%9C%BE%E5%9B%9E%E6%94%B6%E5%99%A8/" title="JVM系列-第12章-垃圾回收器">JVM系列-第12章-垃圾回收器</a><time datetime="2021-11-19T10:33:24.000Z" title="发表于 2021-11-19 18:33:24">2021-11-19</time></div></div></div></div></div></div></main><footer id="footer"><div id="footer-wrap"><div class="copyright">&copy;2020 - 2023 By Alix</div><div class="framework-info"><span>框架 </span><a target="_blank" rel="noopener" href="https://hexo.io">Hexo</a><span class="footer-separator">|</span><span>主题 </span><a target="_blank" rel="noopener" href="https://github.com/jerryc127/hexo-theme-butterfly">Butterfly</a></div></div></footer></div><div id="rightside"><div id="rightside-config-hide"><button id="readmode" type="button" title="阅读模式"><i class="fas fa-book-open"></i></button><button id="darkmode" type="button" title="浅色和深色模式转换"><i class="fas fa-adjust"></i></button><button id="hide-aside-btn" type="button" title="单栏和双栏切换"><i class="fas fa-arrows-alt-h"></i></button></div><div id="rightside-config-show"><button id="rightside_config" type="button" title="设置"><i class="fas fa-cog fa-spin"></i></button><button class="close" id="mobile-toc-button" type="button" title="目录"><i class="fas fa-list-ul"></i></button><a id="to_comment" href="#post-comment" title="直达评论"><i class="fas fa-comments"></i></a><button id="go-up" type="button" title="回到顶部"><i class="fas fa-arrow-up"></i></button></div></div><div><script src="/js/utils.js"></script><script src="/js/main.js"></script><script src="https://cdn.jsdelivr.net/npm/@fancyapps/ui/dist/fancybox.umd.min.js"></script><script>var preloader = {
  endLoading: () => {
    document.body.style.overflow = 'auto';
    document.getElementById('loading-box').classList.add("loaded")
  },
  initLoading: () => {
    document.body.style.overflow = '';
    document.getElementById('loading-box').classList.remove("loaded")

  }
}
window.addEventListener('load',preloader.endLoading())</script><div class="js-pjax"><script>function loadValine () {
  function initValine () {
    const valine = new Valine(Object.assign({
      el: '#vcomment',
      appId: '',
      appKey: '',
      avatar: 'monsterid',
      serverURLs: '',
      emojiMaps: "",
      path: window.location.pathname,
      visitor: false
    }, null))
  }

  if (typeof Valine === 'function') initValine() 
  else getScript('https://cdn.jsdelivr.net/npm/valine/dist/Valine.min.js').then(initValine)
}

if ('Valine' === 'Valine' || !true) {
  if (true) btf.loadComment(document.getElementById('vcomment'),loadValine)
  else setTimeout(loadValine, 0)
} else {
  function loadOtherComment () {
    loadValine()
  }
}</script><script>function loadDisqus () {
  var disqus_config = function () {
    this.page.url = 'http://example.com/2021/11/13/JVM/JVM%E7%B3%BB%E5%88%97-%E7%AC%AC6%E7%AB%A0-%E6%96%B9%E6%B3%95%E5%8C%BA/'
    this.page.identifier = '/2021/11/13/JVM/JVM%E7%B3%BB%E5%88%97-%E7%AC%AC6%E7%AB%A0-%E6%96%B9%E6%B3%95%E5%8C%BA/'
    this.page.title = 'JVM系列-第6章-方法区'
  };

  window.disqusReset = () => {
    DISQUS.reset({
      reload: true,
      config: disqus_config
    })
  }

  if (window.DISQUS) disqusReset()
  else {
    (function() { 
      var d = document, s = d.createElement('script');
      s.src = 'https://.disqus.com/embed.js';
      s.setAttribute('data-timestamp', +new Date());
      (d.head || d.body).appendChild(s);
    })();
  }

  document.getElementById('darkmode').addEventListener('click', () => {
    setTimeout(() => window.disqusReset(), 200)
  })
}

if ('Valine' === 'Disqus' || !true) {
  if (true) btf.loadComment(document.getElementById('disqus_thread'), loadDisqus)
  else loadDisqus()
} else {
  function loadOtherComment () {
    loadDisqus()
  }
}
</script></div><script async src="https://npm.elemecdn.com/tzy-blog/lib/js/other/sakura.js"></script><script defer="defer" id="ribbon" src="https://cdn.jsdelivr.net/npm/butterfly-extsrc/dist/canvas-ribbon.min.js" size="150" alpha="0.6" zIndex="-1" mobile="false" data-click="false"></script><script defer="defer" id="fluttering_ribbon" mobile="false" src="https://cdn.jsdelivr.net/npm/butterfly-extsrc/dist/canvas-fluttering-ribbon.min.js"></script><script id="click-show-text" src="https://cdn.jsdelivr.net/npm/butterfly-extsrc/dist/click-show-text.min.js" data-mobile="false" data-text="你好,大帅哥,大美女" data-fontsize="15px" data-random="true" async="async"></script><script src="https://cdn.jsdelivr.net/npm/pjax/pjax.min.js"></script><script>let pjaxSelectors = ["head > title","#config-diff","#body-wrap","#rightside-config-hide","#rightside-config-show",".js-pjax"]

var pjax = new Pjax({
  elements: 'a:not([target="_blank"])',
  selectors: pjaxSelectors,
  cacheBust: false,
  analytics: false,
  scrollRestoration: false
})

document.addEventListener('pjax:send', function () {

  // removeEventListener scroll 
  window.tocScrollFn && window.removeEventListener('scroll', window.tocScrollFn)
  window.scrollCollect && window.removeEventListener('scroll', scrollCollect)

  typeof preloader === 'object' && preloader.initLoading()
  document.getElementById('rightside').style.cssText = "opacity: ''; transform: ''"
  
  if (window.aplayers) {
    for (let i = 0; i < window.aplayers.length; i++) {
      if (!window.aplayers[i].options.fixed) {
        window.aplayers[i].destroy()
      }
    }
  }

  typeof typed === 'object' && typed.destroy()

  //reset readmode
  const $bodyClassList = document.body.classList
  $bodyClassList.contains('read-mode') && $bodyClassList.remove('read-mode')

  typeof disqusjs === 'object' && disqusjs.destroy()
})

document.addEventListener('pjax:complete', function () {
  window.refreshFn()

  document.querySelectorAll('script[data-pjax]').forEach(item => {
    const newScript = document.createElement('script')
    const content = item.text || item.textContent || item.innerHTML || ""
    Array.from(item.attributes).forEach(attr => newScript.setAttribute(attr.name, attr.value))
    newScript.appendChild(document.createTextNode(content))
    item.parentNode.replaceChild(newScript, item)
  })

  GLOBAL_CONFIG.islazyload && window.lazyLoadInstance.update()

  typeof chatBtnFn === 'function' && chatBtnFn()
  typeof panguInit === 'function' && panguInit()

  // google analytics
  typeof gtag === 'function' && gtag('config', '', {'page_path': window.location.pathname});

  // baidu analytics
  typeof _hmt === 'object' && _hmt.push(['_trackPageview',window.location.pathname]);

  typeof loadMeting === 'function' && document.getElementsByClassName('aplayer').length && loadMeting()

  // prismjs
  typeof Prism === 'object' && Prism.highlightAll()

  typeof preloader === 'object' && preloader.endLoading()
})

document.addEventListener('pjax:error', (e) => {
  if (e.request.status === 404) {
    pjax.loadUrl('/404.html')
  }
})</script><script async data-pjax src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script></div><script src="/live2dw/lib/L2Dwidget.min.js?094cbace49a39548bed64abff5988b05"></script><script>L2Dwidget.init({"tagMode":false,"debug":false,"model":{"jsonPath":"/live2dw/assets/shizuku.model.json"},"display":{"position":"right","width":150,"height":300,"hOffset":20,"vOffset":-20},"mobile":{"show":false},"log":false,"pluginJsPath":"lib/","pluginModelPath":"assets/","pluginRootPath":"live2dw/"});</script></body></html>